Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A typedef enum in C is a composite construct that combines an enumeration (enum) with a type definition (typedef). It creates a user-defined integer-based data type with named constant values (enumerators) and simultaneously assigns an alias to that type in the ordinary identifier namespace. This eliminates the requirement to prepend the enum keyword during subsequent variable declarations.

Syntax and Structure

The standard declaration of an enumeration requires the enum keyword for variable instantiation:
enum Status {
    STATUS_OK,
    STATUS_ERROR
};

enum Status current_status; /* 'enum' keyword is mandatory */
By applying typedef, you bind an anonymous or tagged enumeration to a new type alias:
typedef enum {
    STATUS_OK,
    STATUS_ERROR
} Status;

Status current_status; /* 'enum' keyword is omitted */

Tag Names vs. Typedef Aliases

A typedef enum can be declared with or without an enumeration tag. C maintains separate namespaces for tags (structs, unions, enums) and ordinary identifiers (variables, functions, typedefs). Anonymous Enum with Typedef:
typedef enum {
    MODE_READ,
    MODE_WRITE
} Mode;
Here, the enumeration has no tag. Mode exists only in the ordinary identifier namespace. Tagged Enum with Typedef:
typedef enum e_Mode {
    MODE_READ,
    MODE_WRITE
} Mode;
Here, e_Mode occupies the tag namespace, while Mode occupies the ordinary identifier namespace. Both enum e_Mode and Mode can be used interchangeably to declare variables.

Enumerator Mechanics

Regardless of the typedef, the enumerators (the named constants inside the block) adhere to strict C rules:
  1. Underlying Type: The enumerators themselves are always constants of type int.
  2. Value Assignment: By default, the first enumerator is assigned the integer value 0. Subsequent enumerators implicitly increment by 1.
  3. Explicit Assignment: Enumerators can be explicitly initialized with constant integer expressions. Uninitialized enumerators following an initialized one will resume incrementing by 1 from the explicit value.
typedef enum {
    BIT_ZERO = 1 << 0,  /* 1 */
    BIT_ONE  = 1 << 1,  /* 2 */
    BIT_TWO  = 1 << 2,  /* 4 */
    BIT_NEXT            /* 5 (Implicitly BIT_TWO + 1) */
} BitMask;

Memory and Sizing

While the enumerators are strictly int, the memory footprint of a variable declared via the typedef enum alias is compiler-dependent. The C standard dictates that the compiler must choose an integer type capable of representing the values of all enumerators within the set. While this is typically signed int or unsigned int, compilers may optimize the storage size. For example, if the highest enumerator value is 5, the compiler might allocate only 1 byte (char) for the typedef enum variable, provided compiler-specific flags (such as GCC’s -fshort-enums) are invoked.

Scope and Namespace Collisions

The enumerators defined within a typedef enum do not possess their own scope. They are injected directly into the scope where the typedef enum is defined (typically global scope).
typedef enum {
    PENDING,
    ACTIVE
} TaskState;

typedef enum {
    PENDING, /* Compiler Error: Redefinition of 'PENDING' */
    RESOLVED
} NetworkState;
Because PENDING is placed in the global ordinary identifier namespace by the first declaration, the second declaration results in a naming collision. The typedef alias (TaskState / NetworkState) does not encapsulate the enumerators.
Master C with Deep Grasping Methodology!Learn More