How Enum Creates Named Integer Constants in C

In the C programming language, the enum (enumeration) keyword allows developers to create user-defined types composed of a group of named integer constants. This article explains the underlying mechanics of enumerations in C, covering declaration syntax, automatic and manual integer value assignment, memory representation, and how enumerators improve code readability and maintainability over raw integer literals or preprocessor directives.

Syntax and Basic Declaration

An enumeration is declared using the enum keyword followed by an optional tag name and a list of enumerators enclosed in curly braces:

enum DaysOfWeek {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY
};

In this declaration, enum DaysOfWeek becomes a user-defined type, and the names inside (SUNDAY, MONDAY, etc.) become globally or locally scoped integer constants depending on where the declaration appears.

Automatic Value Assignment

By default, the C compiler assigns integer values to the enumerators automatically:

  • The first enumerator in the list is assigned the integer value 0.
  • Each subsequent enumerator is assigned a value one greater than the preceding enumerator (value = previous_value + 1).

In the DaysOfWeek example above, SUNDAY evaluates to 0, MONDAY to 1, TUESDAY to 2, and continues sequentially through SATURDAY, which evaluates to 6.

Explicit Value Assignment

C allows programmers to override default numbering by explicitly assigning integer values to any of the enumerators:

enum HttpStatus {
    OK = 200,
    CREATED = 201,
    BAD_REQUEST = 400,
    NOT_FOUND = 404,
    INTERNAL_ERROR = 500
};

When an explicit value is provided to an enumerator without explicitly setting the subsequent ones, the compiler continues incrementing from the most recently defined value:

enum Sequence {
    A = 10,
    B,      /* Evaluates to 11 */
    C = 20,
    D       /* Evaluates to 21 */
};

Negative integers and duplicate values are also permitted. For example, setting two identifiers to the same integer is valid and creates aliases.

Internal Representation and Type Rules

Under the hood, C treats enumeration constants as values of type int. Unlike languages with strong type safety (such as C++ or Rust), C performs implicit conversions between enum types and integers:

  • You can assign any integer value to an enum variable, even if that integer is not one of the named constants.
  • You can use enumeration constants directly inside mathematical expressions, array indexing, and conditional statements.
  • The memory allocated for an enum variable typically matches the size of a standard int (sizeof(int)), though the compiler may use an alternative integer type that fits the required range.

Practical Implementation with Typedef

To avoid typing the enum keyword repeatedly when declaring variables, typedef is commonly used:

typedef enum {
    STATE_IDLE,
    STATE_RUNNING,
    STATE_STOPPED
} ProcessState;

ProcessState currentState = STATE_IDLE;

This pattern creates a distinct alias ProcessState that can be used directly as a type throughout the codebase, making switch-case constructs and function signatures self-documenting compared to using generic integer codes.