One of those few things in C that is elegant because it's simple.

You use enum to describe a special user-defined type which can be equal to one of a certain number of predefined things; for example, you have a structure describing an item in an inventory system, and one of the things this structure must describe is the item's status, which you know will always be equal to "in stock", "out of stock", or "back ordered". You could describe the status of the item with a character string, but that would be inefficient both to store and to check up on. So instead what you say is:

enum partstatus {IN_STOCK,OUT_OF_STOCK,BACK_ORDERED};
And suddenly you have defined a type called "enum partstatus", which you can set equal to one of those three things by saying things like enum partstatus mystatus=IN_STOCK;. (In C++, the "enum" in this line would be optional; C++ would recognize partstatus as being short for enum partstatus.) Enums have scope, so if you create an enum type inside a block it ceases to exist outside the block.

Confused yet? If so, these will probably make things worse: First off, you can declare variables of the enum'd type at the same time you define the enum itself, by putting your variable names (separated by commas) after the {} in the enum definition. Second, you can have nameless enums-- enum {A, B, C} oneshot; is legal, although oneshot will be the only variable of that type you will ever be able to define. This particular quirk is mainly useful because it means you can get around the requirement (the one that C++ removed) of prefixing your variable name with enum. Just use typedef enum {IN_STOCK,OUT_OF_STOCK,BACK_ORDERED} partstatus; for your declaration, and you will be able to use partstatus alone as a type.

Enums are actually handled by the preprocessor. Below the surface, what is going on here is that the compiler is typedefing "enum partstatus" as an int type, assigning the first item in your possible values list to 0, and then assigning each possible value after that as the value of the previous item in the possible values list plus one. It then basically #defines (within the block, of course) all the members of the possible values list to their assigned integer values. Got that? So if we were using the example above, you could say something like (OUT_OF_STOCK==1) and it would return true. C++ tries to break this-- in the C++ spec, they for some reason demand that enum be a "special" type, not an integer, and that it be illegal to assign an enum value to anything other than the enum type that defined it. Luckily, no compiler i have ever seen actually obeys the C++ spec in this regard-- they just go ahead and treat enum's as integers.

You can actually assign specific integer values to the items in the possible values list-- the best way i can explain this is that:

enum ordinalnumber {one=1, two, three, seven=7,eight,nine,ten, zero=0, six=6, four=4, five};
would, within the enclosing block, correctly #define the ordinal numbers one through ten as being equivalent to their integer values.

(enum, by the way, is a good way make your APIs very much more clear. For example, if you read through Apple's header files, you'll see they use enum extensively to pass such values; Microsoft's header files, meanwhile, tend to take the route of using #defines and then passing the value as an integer. So if you're looking at a function in an apple header file setPenType(enum kPenType value);, you can easily search and discover enum kPenType(PEN_TYPE_SOLID=5000, PEN_TYPE_DOTTED, PEN_TYPE_INVIS}; in the beginning of the file. Meanwhile if you're in an MS header file and you see setPenType(int value);, you are at a dead end. If you looked in the documentation you would see that PEN_TYPE_SOLID, PEN_TYPE_DOTTED, and PEN_TYPE_INVIS are your legal values, but if you didn't have the documentation, there is no way you would be able to figure out by yourself that #define PEN_TYPE_SOLID 5000, #define PEN_TYPE_SOLID 5001, etc., are sitting in a different header file along with about 200 other unorganized #defines.)

MySQL also has an enum type. You can assign a field's type to be something like ENUM("in stock", "out of stock", "back ordered").