Friday, August 17, 2012

Using Enumerations in ANSI C

In ANSI C, a enumeration is a collection of integer constants which share something in common.  The enumeration is somewhat of an analogy to a set. Also, enumerations are a better alternative than a group of macrodefinitions.

They can be declared as:
#include<stdio.h>

enum Color
{
   RED ,
   GREEN ,
   BLUE ,
};

int main(void)
{
   printf("RED = %d\nGREEN = %d\nBLUE = %d",RED,GREEN,BLUE);
   return 0;
}
/*Output:
RED = 0
GREEN = 1
BLUE = 2
*/
The constant RED will be initialized by default with 0, GREEN will be initialized with RED+1 (1) and BLUE will be initialized with (GREEN+1).
Using macrodefinitions, the program above would've looked like this:
#include<stdio.h>

#define RED   0
#define GREEN 1
#define BLUE  2

int main(void)
{
   printf("RED = %d\nGREEN = %d\nBLUE = %d",RED,GREEN,BLUE);
   return 0;
}
/*Output:
RED = 0
GREEN = 1
BLUE = 2
*/
Alternatively, if you initialize the enumeration in this way:
#include<stdio.h>

enum Color
{
   RED = 5,
   GREEN,
   BLUE,
};

int main(void)
{
   printf("RED = %d\nGREEN = %d\nBLUE = %d",RED,GREEN,BLUE);
   return 0;
}
/*Output:
RED = 5
GREEN = 6
BLUE = 7
*/
The constant RED will be initialized with 5, GREEN will be initialized with RED+1 (6)  and BLUE will be initialized with GREEN+1 (7).
TIP: You can can also initialize all members of the enumeration with non-default values:
#include<stdio.h>

enum Color
{
   RED = 5,
   GREEN = 7,
   BLUE = 3,
};

int main(void)
{
   printf("RED = %d\nGREEN = %d\nBLUE = %d",RED,GREEN,BLUE);
   return 0;
}
/*Output:
RED = 5
GREEN = 7
BLUE = 3
*/
TIP: If you don't initialize the first member of the enumeration, he will be equal to 0 by default even if you initialize other members:
#include<stdio.h>

enum Color
{
   RED ,
   GREEN ,
   BLUE =7,
};

int main(void)
{
   printf("RED = %d\nGREEN = %d\nBLUE = %d",RED,GREEN,BLUE);
   return 0;
}
/*Output:
RED = 0
GREEN = 1
BLUE = 7
*/
If you want to declare a Color variable you will have to put the keyword enum in front of it:
#include<stdio.h>

enum Color
{
   RED ,
   GREEN ,
   BLUE =7,
};

int main(void)
{
   enum Color myColor = RED;
   switch(myColor)
   {
      case RED:
           puts("My color is red");
           break;
      case GREEN:
           puts("My color is green");
           break;
      case BLUE:
           puts("My color is blue");
           break;
   }
   return 0;
}
/*Output:
My color is red
*/
Alternatively, if you want a shorter declaration you could use typedef:
#include<stdio.h>

enum Color
{
   RED ,
   GREEN ,
   BLUE =7,
};

typedef enum Color eColor;

int main(void)
{
   eColor myColor = RED;
   switch(myColor)
   {
      case RED:
           puts("My color is red");
           break;
      case GREEN:
           puts("My color is green");
           break;
      case BLUE:
           puts("My color is blue");
           break;
   }
   return 0;
}
/*Output:
My color is red
*/
TIP: A shorter version of the declaration above is:
#include<stdio.h>

typedef enum
{
   RED ,
   GREEN ,
   BLUE =7,
}eColor;

int main(void)
{
   eColor myColor = RED;
   switch(myColor)
   {
      case RED:
           puts("My color is red");
           break;
      case GREEN:
           puts("My color is green");
           break;
      case BLUE:
           puts("My color is blue");
           break;
   }
   return 0;
}
/*Output:
My color is red
*/
TIP: Also, multiple members of an enumeration can have the same constant value:
#include<stdio.h>

typedef enum
{
   RED    = 0,
   GREEN  = 1,
   BLUE    =1,
}eColor;

int main(void)
{
   puts("This WILL NOT trigger an error");
   printf("RED = %d\nGREEN = %d\nBLUE = %d",RED,GREEN,BLUE);
   return 0;
}
/*Output
This WILL NOT trigger an error
RED = 0
GREEN = 1
BLUE = 1
*/
TIP: A debugger may be able to print values of enumeration variables in their symbolic form.

PITFALL: A common error that you may encounter while working with enumeration is the enumerator redeclaration as in the example below.
#include<stdio.h>

typedef enum
{
   RED    = 0,
   GREEN  = 1,
   BLUE    =1,
}CarColor;

typedef enum
{
    RED,        //RED is redeclarated
    YELLOW,
    MAGENDA
}WallColor;

int main(void)
{
   puts("This WILL NOT trigger an error");
   printf("RED = %d\nGREEN = %d\nBLUE = %d",RED,GREEN,BLUE);
   return 0;
}
/*Output
../main.c:20:5: error: redeclaration of enumerator ‘RED’
*/
TIP : The easiest way to solve such an issue is to adopt the following notation for enumerators: EnumName_EnumeratorDescription.
#include<stdio.h>

typedef enum
{
   CARCOLOR_RED    = 0,
   CARCOLOR_GREEN  = 1,
   CARCOLOR_BLUE   = 1,
}CarColor;

typedef enum
{
   WALLCOLOR_RED,        
   WALLCOLOR_YELLOW,
   WALLCOLOR_MAGENTA
}WallColor;

int main(void)
{
   printf("RED = %d\nGREEN = %d\nBLUE = %d",
           CARCOLOR_RED,CARCOLOR_GREEN,CARCOLOR_BLUE);
   return 0;
}
/*Output
RED = 0
GREEN = 1
BLUE = 1
*/
In conclusion, enumerations provide a convenient way to associate constant values with names as a more elegant alternative to multiple #define.

Question: What other pitfalls regarding enums do you know?

References:
http://tigcc.ticalc.org/doc/keywords.html#enum
http://en.wikipedia.org/wiki/Enumerated_type#C_and_syntactically_similar_languages
http://cplus.about.com/od/introductiontoprogramming/p/enumeration.htm
http://msdn.microsoft.com/en-us/library/whbyts4t.aspx

No comments:

Post a Comment

Got a question regarding something in the article? Leave me a comment and I will get back at you as soon as I can!

Related Posts Plugin for WordPress, Blogger...
Recommended Post Slide Out For Blogger