C Language Essential Knowledge: Enumeration (
enum)
The enum type was introduced with the ANSI C standard to improve code readability, correctness, and maintainability. When a variable can take only a limited and well-defined set of values, an enumeration is often the most appropriate representation.
An enumeration explicitly lists all valid values for a variable, restricting it to a controlled domain. This makes intent clearer, reduces errors caused by magic numbers, and improves self-documentation—especially important in embedded and safety-critical software.
🧩 Defining Enumerations #
The general syntax for defining an enumeration type is:
enum EnumTypeName
{
EnumeratorList /* list of named integer constants */
} EnumVariableList;
You may:
- Declare the enumeration type first and define variables later, or
- Declare the type and variables at the same time.
🧪 Common Declaration Patterns #
Declaring the Type First, Then Defining Variables #
enum weekday
{
sun,
mon,
tue,
wed,
thu,
fri,
sat
};
enum weekday workday, week_end;
This approach is preferred when the enumeration type is reused across multiple source files or APIs.
Declaring Type and Variables Simultaneously (Anonymous Enum) #
enum
{
sun,
mon,
tue,
wed,
thu,
fri,
sat
} workday, week_end;
Anonymous enums are useful for local scope usage, but they cannot be referenced by name elsewhere.
🧠 Using Enumerations #
By default, the enum values are assigned consecutive integers starting from 0, in the order they are listed.
#include <stdio.h>
enum weekday
{
sun, /* 0 */
mon, /* 1 */
tue /* 2 */
};
enum weekday workday;
int main(void)
{
workday = mon;
printf("workday = %d\r\n", workday);
return 0;
}
Output:
workday = 1
📌 Important Rules and Behavior #
-
Compile-Time Constants Enumerators (
sun,mon, etc.) are treated as integer constants, not variables. Their values cannot be modified at runtime. -
Default and Explicit Values If no value is specified, enumeration starts at 0 and increments by 1. Explicit assignment is allowed:
enum example { A = 10, B, C = 20, D }; /* A=10, B=11, C=20, D=21 */ -
Comparisons Are Allowed Enumeration values can be compared and used in control flow:
if (workday == mon) { /* ... */ } -
Integer Assignment Requires Casting Assigning a raw integer to an enum variable requires an explicit cast:
workday = (enum weekday)2; /* allowed */ /* workday = 2; */ /* may trigger warning */This rule helps catch invalid assignments during compilation.
🔧 Enumerations in Embedded and MCU Programming #
Enumerations are extensively used in embedded systems to describe hardware states, configurations, and control modes. They improve clarity and reduce configuration errors.
GPIO Mode Enumeration #
Defines the operating mode of a GPIO pin:
/**
* @brief GPIO Configuration Mode enumeration
*/
typedef enum
{
GPIO_Mode_IN = 0x00, /* Input mode */
GPIO_Mode_OUT = 0x01, /* Output mode */
GPIO_Mode_AF = 0x02, /* Alternate function */
GPIO_Mode_AN = 0x03 /* Analog mode */
} GPIOMode_TypeDef;
GPIO Output Speed Enumeration #
Defines the maximum output speed of a GPIO pin:
/**
* @brief GPIO Output speed enumeration
*/
typedef enum
{
GPIO_Low_Speed = 0x00,
GPIO_Medium_Speed = 0x01,
GPIO_Fast_Speed = 0x02,
GPIO_High_Speed = 0x03
} GPIOSpeed_TypeDef;
These enums are typically mapped directly to hardware registers, making the code self-explanatory while still maintaining full control over bit-level values.
📝 Summary #
The enum type is a simple but powerful feature of C that brings structure and meaning to otherwise opaque integer values. In embedded systems, enums are indispensable for representing states, modes, and configurations in a safe and readable way.
Used correctly, enumerations:
- Improve code clarity
- Reduce configuration mistakes
- Enhance maintainability
- Align well with register-level programming
For mission-critical and long-lived embedded software, disciplined use of enum is a best practice—not a convenience.