C Enums
An enum in C is a user-defined type made from named integer constants. Enums make code easier to read when a value must be one choice from a small fixed set.
Instead of using plain numbers such as 0, 1, and 2, you can give those values meaningful names such as LOW, MEDIUM, and HIGH.
Enum Syntax
Use the enum keyword, followed by a type name and a list of names inside braces. Each name is called an enumerator.
#include <stdio.h>
enum Level {
LOW,
MEDIUM,
HIGH
};
int main(void)
{
enum Level current = MEDIUM;
printf("LOW = %d\n", LOW);
printf("MEDIUM = %d\n", MEDIUM);
printf("HIGH = %d\n", HIGH);
printf("Current level: %d\n", current);
return 0;
}
Output:
LOW = 0
MEDIUM = 1
HIGH = 2
Current level: 1
By default, the first enumerator has the value 0, the next has 1, and so on. The variable current has type enum Level, and it stores one of the named values from that enum.
Custom Enum Values
You can assign specific integer values to enumerators. This is useful when the numbers must match a file format, protocol, database value, or another part of a program.
#include <stdio.h>
enum Status {
STATUS_NEW = 1,
STATUS_PROCESSING = 2,
STATUS_DONE = 3
};
void print_status(enum Status status)
{
switch (status) {
case STATUS_NEW:
printf("Order is new.\n");
break;
case STATUS_PROCESSING:
printf("Order is being processed.\n");
break;
case STATUS_DONE:
printf("Order is done.\n");
break;
default:
printf("Unknown status.\n");
break;
}
}
int main(void)
{
enum Status order_status = STATUS_PROCESSING;
print_status(order_status);
return 0;
}
Output:
Order is being processed.
The switch statement reads naturally because each case uses a named enum value. This is clearer than writing case 1, case 2, and case 3 without explanation.
Enums As Tags
Enums are often used with structures and unions. A union stores one active member at a time, and an enum can describe which member is currently valid.
#include <stdio.h>
enum ValueType {
TYPE_INT,
TYPE_DOUBLE
};
union Data {
int whole;
double decimal;
};
struct StoredValue {
enum ValueType type;
union Data data;
};
void print_value(struct StoredValue value)
{
if (value.type == TYPE_INT) {
printf("Stored int: %d\n", value.data.whole);
} else if (value.type == TYPE_DOUBLE) {
printf("Stored double: %.2f\n", value.data.decimal);
}
}
int main(void)
{
struct StoredValue first = {TYPE_INT, {.whole = 42}};
struct StoredValue second = {TYPE_DOUBLE, {.decimal = 3.75}};
print_value(first);
print_value(second);
return 0;
}
Output:
Stored int: 42
Stored double: 3.75
Here, type is an enum tag. If it is TYPE_INT, the program reads data.whole. If it is TYPE_DOUBLE, the program reads data.decimal. This makes the union safer and easier to understand.
Important Enum Rules
- Define an enum with
enum Name { ... };. - Enumerator names are integer constants.
- Default enum values start at
0and increase by1. - You can assign custom integer values with
=. - Enums improve readability, but C still stores them as integer-like values.
The key idea is that enums replace unclear numeric codes with meaningful names. Next, typedef can make custom type names shorter to write.
