CEnumerations

Enumerations

An enum lets you give meaningful names to a set of related integer constants, instead of scattering unexplained numbers throughout your code. It does not introduce a new kind of storage — under the hood, an enum value is just an int — but it makes code dramatically easier to read and maintain.

Declaring and using an enum

C
#include <stdio.h>

enum Day {
    MONDAY,     // 0
    TUESDAY,    // 1
    WEDNESDAY,  // 2
    THURSDAY,   // 3
    FRIDAY,     // 4
    SATURDAY,   // 5
    SUNDAY      // 6
};

int main(void) {
    enum Day today = WEDNESDAY;

    printf("today = %d\n", today);

    if (today == SATURDAY || today == SUNDAY) {
        printf("weekend!\n");
    } else {
        printf("weekday\n");
    }

    return 0;
}
today = 2
weekday
Default values: 0, then +1 each

Unless you say otherwise, the first name in an enum is 0 and each subsequent name is one more than the previous. You can override any individual value explicitly, and the automatic numbering continues from wherever you left off:

C
enum StatusCode {
    OK = 200,
    CREATED,        // 201 -- continues from OK
    BAD_REQUEST = 400,
    UNAUTHORIZED,   // 401 -- continues from BAD_REQUEST
    NOT_FOUND       // 402!  easy to get wrong -- see note below
};
Watch the numbering after an explicit value
`NOT_FOUND` above becomes `402`, not the `404` you might expect, because it simply continues incrementing from `UNAUTHORIZED = 401`. If you mix automatic and explicit values, give every value that matters an explicit number to avoid this kind of surprise.
Why enums beat magic numbers

Compare if (status == 3) to if (status == STATUS_ERROR). The second version documents itself: anyone reading the code (including you, months later) immediately knows what the comparison means, without needing to look up what 3 represents. Enums also make it easy to change the underlying numbers later without hunting down every literal 3 in the codebase.

C enums are not type-safe
An enum variable is really just an int
Unlike enums in some other languages, a C `enum Day` variable is not restricted to the named values — it is an `int` in disguise, and the compiler generally will not stop you from assigning it any integer value at all, including ones that do not correspond to any named constant.

C
enum Day today = 99;   // compiles on most compilers, even though
                       // 99 is not one of the named Day values

if (today == MONDAY) {
    // never true, but nothing warns you that today is meaningless
}

Because of this, code that receives an enum value from an untrusted source (a file, network input, a cast from a raw integer) should validate it against the known range of valid values before trusting it, rather than assuming it must be one of the named constants.

  • Enum values default to 0, 1, 2, ... in declaration order unless given an explicit value.

  • Assigning one value explicitly changes the automatic count for every subsequent unassigned name.

  • Enums make code self-documenting compared to unexplained numeric literals.

  • A C enum variable is really an int and can hold any integer value, not just the named ones — validate values from untrusted sources.