[Tutorial] Enumerators (enums). What they actually are?
#1

Enumerators
There is something about enums that many scripters aren't aware of.

There are many of you using enums in your script for storing Player/Vehicle/House Data etc. (Especially user info)

A typical (or very common) example:
pawn Code:
enum
    e_PlayerInfo
{
    SCORE,
    MONEY,
    KILLS,
    DEATHS
};

new pInfo[MAX_PLAYERS][e_PlayerInfo];
Now, this is how it's used:

pawn Code:
public OnPlayerDeath(playerid, killerid, reason)
{
    pInfo[playerid][DEATHS]++;
   
    if(IsPlayerConnected(killerid) && killerid != playerid)
    pInfo[killerid][KILLS]++;
   
    return 1;
}
Alright, now that's easily understood.

Now:
pawn Code:
enum
    e_PlayerInfo
{
    SCORE,
    MONEY = 9,
    KILLS = 5,
    DEATHS = 56
};

new pInfo[MAX_PLAYERS][e_PlayerInfo];

printf("%i | %i | %i | %i", pInfo[0][SCORE], pInfo[0][MONEY], pInfo[0][KILLS], pInfo[0][DEATHS]);
So, the output will be "0 | 9 | 5 | 56", right?


If you think "yeah"..

Wrong, because it will give: "0 | 0 | 0 | 0", you might think that enums are the ones that store data.
When I did "MONEY = 9" in the enum, then used "pInfo[0][MONEY]" in the printf, it considered it as pInfo[0][9] not ePlayerInfo:MONEY. Which means I used "MONEY" as an index for my pInfo variable.

So, enums are NOT variables at all! They are actually "constants", they only help you in assigning a particular name to your variable index.

Ok, Let's get a bit deeper and hopefully you'll understand more..

Example:
pawn Code:
const e_CAR1 = 0;
const e_CAR2 = 1;
const e_CAR3 = 2;

new MyCars[3];

main()
{
    MyCars[e_CAR1] = 520;
    MyCars[e_CAR2] = 458;
    MyCars[e_CAR3] = 411;
}
We'll do the same thing with enums now:
pawn Code:
enum
    e_TEST
{
    e_CAR1,
    e_CAR2,
    e_CAR3
};

new MyCars[e_TEST];

main()
{
    MyCars[e_CAR1] = 520;
    MyCars[e_CAR2] = 458;
    MyCars[e_CAR3] = 411;
}
Both (using const and enums here) will compile fine and do the same thing, Do you see a difference?
Yes, only in how you create the code.

This piece of code I showed you, tells you that enums do the same things as constants.
But there are few differences which makes us use enums rather than constants or definitions (const e_CAR1 = 0; or #define e_CAR1 0) We'll talk about the differences later.

First you should understand how enums are structured:
pawn Code:
enum TEST
{
   Abc,
   Def,
   Ghi,
};
Abc is a constant with the value of 0 (Almost same as doing const Abc = 0; or #define Abc 0),
Def is a const of value 1 (const Def = 1; or #define Def 1)
And Ghi is a const of value 2 (const Ghi = 2; or #define Ghi 2)

The pre-compiler automatically sets the values of these constants starting from 0 to .. n
Whereas in making constants, you are the one who has to assign it. But in enum, it's automatically structured.


Example:
pawn Code:
enum TEST
{
   e_ONE, //This will automatically get "0"
   e_TWO,  //this: "1"
   e_THREE,  // "2"
   e_FOUR = 12, // Now, here's a difference, since you assigned "12" to it, instead of being "3", it'll become 12..
   e_FIVE, //This will be 13 because it's upper enumerator had "12"
   e_SIX //This will be 14. It's upper: "13"
}
As you can see, if you assign one yourself (like I did "e_FOUR = 12") The next enumerator will have e_FOUR+1 and so on..

Some more explanations:

pawn Code:
enum
    DATA
{
    INT, //This will get "0" (Remember, starting value)
    STRING[10], //(This will get 1 but since it's a string, just one block isn't sufficient!)
        //^ So, the correct numbers will be: 1,2,3,4,5,6,7,8,9,10! Because length of the string is 10!
    INT2, //This will get the number 11, it comes after STRING[10] which had the last number of 10..
    STRING2[10] //And this will start with 12 and end to 22 because it requires 10 spaces.
};
Using
pawn Code:
printf("%i", _:DATA);
I got: "22"

Because the size of the whole enum is 22.
INT, STRING, INT2, STRING2
1+ 10+ 1+ 10 = 22

Now, you might think why I used "1" to show INT and not "0"?
The thing is, I'm showing you "HOW MANY" blocks are being used by INT, not "WHICH ONE".
If it was "which one", then it would be "0", block 0 is occupied by INT.

For a block of size 22, these are the indexes "0..1..2 till 19..20..21" < You have 22 numbers here.

Using
pawn Code:
printf("%i", _:STRING);
I got: "1"

because the first block was occupied by INT which is "0"
And therefore, STRING started from block "1"

If I show the usage of blocks by each enumerator, it will look like:

INT : block 0
STRING : blocks 1,2,3,4,5,6,7,8,9,10
INT2 : block 11
STRING2 : blocks 12,13,14,15,16,17,18,19,20,21

Using
pawn Code:
new Array[DATA];
    printf("%i", sizeof Array);
Also gave me 22, because, yeah, "DATA" had the size of 22.

Finally, we see that Array is actually:

Array[INT + STRING + INT2 + STRING2];
(will not compile, just visualize it)

Therefore, whenever you use enums, you use the actual variable & enumerators as indexes.

A diagrammatic example:


Another Example:

pawn Code:
enum
    TEST
{
    SomeInteger = 124,
    SomeString[12],
    Float:SomeFloat
};

public OnFilterScriptInit()
{
    new var_TEST[TEST];
   
    var_TEST[SomeInteger] = 1337;
   
    printf("1) Stored in var: %i, Constant: %i", var_TEST[SomeInteger], _:SomeInteger); //1
   
    format(var_TEST[SomeString], 12, "Hey!");
   
    printf("2) Stored in var: %s, Constant: %i", var_TEST[SomeString], _:SomeString); //2
   
    var_TEST[SomeFloat] = 2054.124;
   
    printf("3) Stored in var: %f, Constant: %i", var_TEST[SomeFloat], _:SomeFloat); //3
   
    return true;
}
Outputs:
1) "Stored in var: 1337, Constant: 124"

As you've seen, I assigned var_TEST[SomeInteger] with 1337.
And in the enumerations, SomeInteger has a constant value of 124.

2) "Stored in var: Hey!, Constant: 125"
Here, I assigned var_TEST[SomeString] with "Hey!".
And in the enumerations, SomeString has a size of 12, but it printed 125

because, 125 is the starting block of the string, it ends to 125 + 12.

3) "Stored in var: 2054.124023, Constant: 137"
Floating point printed out normally, but SomeFloat printed out to be "137"!
It's supposed to be 126 right? Because it was created after SomeString which had the value of 125..

But, since SomeString[12] is an Array (String), it ate up 12 more spaces. Which made SomeFloat to get the value of 137
(Note that 125 + 12 = 137)

Some more important information:

Enums can also be used as tags:

pawn Code:
enum E_EG
{
    E_FIRST = 4,
    E_SECOND = 2
}

Now, I can do:
pawn Code:
new E_EG:SomeVar;
And:

pawn Code:
new E_EG:MyVariable = E_FIRST; // No warnings despite using "E_FIRST".
//Because E_FIRST is already a part of the E_EG enumerator
//Since we tagged MyVariable with E_EG, it's all fine with E_FIRST.
pawn Code:
new data[E_EG];
    data[E_FIRST] = 7; // Compiler error - index out of bounds
    //Because, the value of E_EG is 3 and E_FIRST is 4 (the index doesn't exist)
Anonymous Enums:
pawn Code:
enum //<< We didn't give it a name.
{
    E_TEST[10] = 32,
    E_VAR
};


main()
{
    new data[E_TEST]; //E_TEST = 32 not 10.
    //Note that we also didn't use any tag _:E_TEST
}
Strong & Weak tags:

pawn Code:
enum
    E_STRONG //< Since the name starts with a capital letter, the tag is considered "Strong"
{
    E_VAR = 64
};

main()
{
   
    new Test = E_STRONG:E_VAR;
    //Will give you a warning: "tag mismatch" because "Test" doesn't have E_STRONG tag
   
    #pragma unused Test
}
pawn Code:
enum
    e_WEAK //< And here it starts with small letter, so the enum creates a weak tag.
{
    E_VAR = 64
};

main()
{
   
    new Test = e_WEAK:E_VAR;
    //No warning...
   
    #pragma unused Test
}
That's almost everything about enums, and these are the reasons why we prefer to use enums..

* Thanks to Y_Less for his explanations.
Reply
#2

Interesting tutorial. Never known some of the things. Pretty creative work!
Reply
#3

Awesome Work ! good luck on your future tutorials.
Second comment ya
Reply
#4

Quote:
Originally Posted by ServerScripter
View Post
Awesome Work ! good luck on your future tutorials.
Second comment ya
Quote:
Originally Posted by T0pAz
View Post
Interesting tutorial. Never known some of the things. Pretty creative work!
Thanks guys!

Quote:
Originally Posted by Y_Less
View Post
Some other points for you:
"E_EG" is both a tag and a constant. You can also have anonymous enums and "strong" and "weak" enum tags.
Added & thanks again.
Reply
#5

Dude , Good job - That was very usefull to me
Reply
#6

Quote:
Originally Posted by Breto
View Post
Dude , Good job - That was very usefull to me
Thanks.

- Done few corrections and improvements.
Reply
#7

You should consider adding this to the wiki too.
Reply
#8

Quote:
Originally Posted by Calgon
View Post
You should consider adding this to the wiki too.
Alright, but I'm having trouble registering there.
When I click on "Create Account", It keeps on showing me "Login" menu, I don't see any registration menu..

What am I doing wrong?

Quote:
Originally Posted by DeaDly_Evil
View Post
Awesome tutorial Well Explained!
Thanks!
Reply
#9

Wiki account registrations have been disabled a while back due to constant link spammers/advertisers registering. You could try contacting Dugi on IRC or via PM to make him create an account for you. He's the only bureaucrat, besides Kalcor himself.
Reply
#10

Quote:
Originally Posted by Vince
View Post
Wiki account registrations have been disabled a while back due to constant link spammers/advertisers registering. You could try contacting Dugi on IRC or via PM to make him create an account for you. He's the only bureaucrat, besides Kalcor himself.
Ok thank you, I'll contact him soon.
Reply
#11

Both of your tutorials are great. I didn't really know some of the things, so I think every wannabe scripter should take a look at this before saying "jaja Im pro im the best" ...
Reply
#12

Wow, didn't know all of these things about enumerators. Thanks for the tutorial, finally I understand those :P
Reply
#13

Nice Tutorial.
Reply
#14

Nice tutorial...

And we can use enums for example:

pawn Code:
enum Info
{
    Some,
    Else,
    More
}
new Data[MAX_PLAYERS][Info];
And we usually use it like (example):

pawn Code:
Data[playerid][Some] = 2;
Data[playerid][Else] = 1456416;
but we can use it:

pawn Code:
Data[playerid][Info:0] = 2; //Is the same like Data[playerid][Some]
Data[playerid][Info:1] = 1456416
p.s sorry if you already post it :S
Reply
#15

Wow is all I can say.
Learnt some new things after reading this.
Reply
#16

Thanks a lot, you learnt me many things I have not known before.
Reply
#17

Really Userful Tutorial for Beginner Scripters. Thanks for this piece of Information! +REP!
Reply
#18

Is it possible to

static enum ?
Reply
#19

Quote:
Originally Posted by Sniper Kitty
View Post
Is it possible to

static enum ?
pawn Code:
enum {
    VALUE_IS_0,
    VALUE_IS_1,
    VALUE_IS_2
}

main() {
    printf("%d", VALUE_IS_1); // prints 1
}
Reply
#20

So how would you add some data in one of the enums in the beginning? For example, like you would do with an array:

Code:
new example[3] = {1,2,3};
How would you do that if you're using enumeration:

Code:
enum EXAMPLE
{
       EX_1,
       EX_2[3]
}

new myarray[EXAMPLE];
Let's say I want to put 3 static values in EX_2, how to do that?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)