Enumerations are integers, except when they're not

August 18, 2008

Dan_Saks-August 18, 2008

I recently explained that although both C and C++ provide void * as the generic data pointer type, each language treats the type a little differently.1 For any object type T, both C and C++ let you implicitly convert an object of type T * to void *. (An implicit conversion is one that doesn't require a cast.) However, only C lets you implicitly convert in the opposite direction--from void * to T *.

There's a similar disparity in the way the two languages treat enumeration values. Both C and C++ let you implicitly convert an enumeration value into an int. However, only C lets you implicitly convert an int into an enumeration.

For example, consider these enumeration definitions:

enum day
    Sun = day_begin, Mon, Tue, ... , Sat,
typedef enum day day;

enum month
    Jan = month_begin, Feb, Mar, ... , Dec,
typedef enum month month;

The identifier appearing immediately after the keyword enum is a tag, not a type. I typically define a type name with the same spelling as each tag and then just use the type name.2 I often define additional _begin and _end enumeration constants to facilitate writing loops, like the one you'll see shortly.3

In C, each enumeration constant has type int and each enumeration type is compatible with some integer type. (The integer types include all three character types--plain, signed, and unsigned.) The choice of compatible type is implementation-defined. The C standard grants the freedom to use different integer types to represent different enumeration types, but most compilers just use int to represent all enumeration types.

Treating enumerations as just integers leads to some useful behaviors. For example, C lets you apply all the usual integer operations to enumerations, so you can easily write loops that iterate over a range of enumeration values, as in:

day d;
for (d = day_begin; d != day_end; ++d)

Unfortunately, C also lets you do highly questionable things with enumerations such as:

day d;
month m;
d = Dec;        // assign a month to a day
m = 31;         // assign an arbitrary int to a month
if (d < m)      // compare a day with a month

< Previous
Page 1 of 2
Next >

Loading comments...