Back to C Programming
2026-04-219 min read

enum (C Programming)

Learn enum (C Programming) step by step with clear examples and exercises.

Why This Matters

Enumerations are a powerful and essential part of the C programming language, providing developers with a way to define custom data types consisting of a set of named values. By using enumerations, you can:

  1. Organize related constants in a single place, making your code cleaner and easier to understand.
  2. Ensure type safety by restricting variables to only accept the defined values, preventing potential errors caused by incorrect data types.
  3. Improve readability by giving meaningful names to constants, making your code more accessible for other developers working on your projects in the future.
  4. use enumerations in various areas such as game development, system programming, and network protocols due to their versatility and ease of use.
  5. Reduce the likelihood of naming collisions between constants by using a consistent naming convention for your enumerated types.
  6. Facilitate code maintenance as changes to enumeration values only require modifying the enumeration definition, not every instance where it is used.
  7. Encourage consistency and adherence to coding standards within a team or project.

Prerequisites

To fully grasp enumerations, you should have a good understanding of:

  1. Basic C syntax, including variables, data types, and operators.
  2. Control structures like loops and conditional statements.
  3. Understanding the concept of memory allocation in C.
  4. Familiarity with basic input/output operations using functions like printf() and scanf().
  5. A solid understanding of C's data types, such as integers, floats, and characters.
  6. Knowledge of pointers and their role in memory management in C.
  7. Understanding the concept of scope in C (global, function, block).
  8. Familiarity with bitwise operations in C.
  9. Knowledge of structures and unions in C.
  10. Comfort with using header files and libraries in C.

Core Concept

An enumerated type is a distinct data type whose values are the values of its underlying type, which includes the explicitly named constants (enumeration constants). Enumerations are declared using the enum keyword followed by an identifier and a set of enumerators enclosed in curly braces.

enum color { RED, GREEN, BLUE };

In this example, we have defined an enumerated type called color, which has three enumeration constants: RED, GREEN, and BLUE. By default, the underlying type of an enumeration is int, and the enumeration constants are assigned values starting from 0. However, you can specify a different underlying type using the following syntax:

enum color : unsigned char { RED, GREEN, BLUE };

In this case, we have explicitly specified that the underlying type of color should be unsigned char.

Enumeration constants and their values

Enumeration constants are automatically assigned integer values starting from 0. However, you can manually assign values to enumeration constants by providing an initializer list when declaring the enumerated type. For example:

enum days { SUNDAY = 0, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };

In this example, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, and SATURDAY are assigned values of 1, 2, 3, 4, 5, and 6 respectively. The value of SUNDAY remains 0 since it has an explicit initializer.

Enumeration constants as bit fields

By using the enum keyword followed by a colon (:) and the desired underlying type, you can specify that enumeration constants should be treated as bit fields. This allows you to pack multiple enumeration constants into a single integer variable, saving memory and improving performance in certain scenarios. For example:

enum flags { FLAG_A = 1 << 0, FLAG_B = 1 << 1, FLAG_C = 1 << 2 };
int my_flags = FLAG_A | FLAG_B;

In this example, we have defined an enumerated type called flags, and the enumeration constants are treated as bit fields. The variable my_flags now contains the values of both FLAG_A and FLAG_B.

Worked Example

Let's create a simple program that demonstrates enumerations:

#include <stdio.h>

// Define an enumerated type called color with bit fields
enum color : unsigned char { RED = 1, GREEN = 2, BLUE = 4 };

int main() {
// Create a variable of the defined enum type and assign it multiple flags
enum color my_color = RED | GREEN;

printf("The current color is: ");
if (my_color & RED) printf("RED ");
if (my_color & GREEN) printf("GREEN ");
if (my_color & BLUE) printf("BLUE\n");

return 0;
}

In this example, we define an enumerated type called color, and the enumeration constants are treated as bit fields. We then create a variable my_color of that type and assign it multiple flags (RED and GREEN). In the main() function, we print out the current color based on the value of my_color.

Using enumeration constants in expressions

Enumeration constants can be used in expressions just like regular integer constants. For example:

enum color my_color = RED + 1; // my_color will be assigned the value GREEN (since enumeration constants are integers)

Enumeration constants as array indices

Be careful when using enumeration constants as array indices, as their underlying type may not always match the array's data type. This can lead to unexpected behavior and potential errors. To work around this, you can cast the enumeration constant to size_t before using it as an index:

int my_array[3] = { 1, 2, 3 };
printf("%d\n", my_array[(size_t)RED]); // prints "1"

Common Mistakes

  1. Forgetting to initialize enumeration constants: If you don't explicitly assign values to your enumeration constants, they will be assigned default values starting from 0. However, this can lead to confusion when dealing with larger enumerations.
  2. Misunderstanding the underlying type: Be aware that the underlying type of an enumeration is int by default. If you're working with a large number of enumeration constants or dealing with memory constraints, it may be beneficial to specify a different underlying type.
  3. Not defining enumeration types before using them: Enumeration types must be defined before they can be used in your code. Make sure to declare them at the appropriate scope (e.g., global, function, or block).
  4. Using enumeration constants as array indices without casting: This can lead to unexpected behavior and potential errors due to type mismatches between the enumeration constant and size_t.
  5. Comparing enumeration constants with regular integers: Note that that enumeration constants are implicitly converted to their underlying type when used in expressions. Comparing an enumeration constant to a regular integer may result in unexpected behavior if the two types don't match.
  6. Treating enumeration constants as boolean values without explicit conversion: Enumeration constants are integers by default, so treating them as boolean values without explicit conversion can lead to incorrect results.
  7. Using bitwise operations on enumerations with non-bit field underlying types: This may result in unexpected behavior due to the way enumeration constants are stored in memory.
  8. Not following a consistent naming convention for enumerated types and their constants: Using a consistent naming convention can improve readability and reduce the likelihood of naming collisions between constants.
  9. Using enumerations without considering performance implications: While enumerations can make your code more readable, they may have a negative impact on performance due to increased memory usage or reduced compiler optimizations. Be aware of these trade-offs when deciding whether to use enumerations in your code.
  10. Not documenting the meaning and purpose of enumerated types and their constants: Proper documentation can help other developers understand the intended usage of your enumerations, reducing confusion and improving maintainability.

Common Mistakes - Subheadings

  • Forgetting to initialize enumeration constants
  • Misunderstanding the underlying type
  • Not defining enumeration types before using them
  • Using enumeration constants as array indices without casting
  • Comparing enumeration constants with regular integers
  • Treating enumeration constants as boolean values without explicit conversion
  • Using bitwise operations on enumerations with non-bit field underlying types
  • Not following a consistent naming convention for enumerated types and their constants
  • Using enumerations without considering performance implications
  • Not documenting the meaning and purpose of enumerated types and their constants

Practice Questions

  1. Define an enumerated type called shape with the values CIRCLE, RECTANGLE, and TRIANGLE. Create a variable of this type and assign it the value CIRCLE.
  2. Write a function that takes an enumeration constant as an argument and prints out its corresponding name (e.g., "CIRCLE" for CIRCLE).
  3. Modify the worked example to accept user input specifying the color, and print out a message based on the chosen color.
  4. Write a program that declares an enumerated type called days, assigns values to each day of the week, and prints out the number of days between two given days (e.g., if the user inputs SUNDAY and WEDNESDAY, the program should output "3").
  5. Write a program that defines an enumerated type called flags, where each flag corresponds to a specific feature in a software application. The program should then prompt the user to enter a combination of flags, and based on the entered flags, print out a message describing which features are enabled or disabled.
  6. Write a program that uses bit fields to represent the state of a traffic light (RED, YELLOW, GREEN). The program should accept user input specifying the desired sequence of colors for the traffic light, and then simulate the corresponding sequence by printing out the current color at each step.
  7. Write a program that defines an enumerated type called operators, with values representing various mathematical operators (e.g., ADD, SUBTRACT, MULTIPLY, DIVIDE). The program should prompt the user to enter two numbers and an operator, perform the corresponding operation, and print out the result.
  8. Write a program that defines an enumerated type called sort_order, with values representing different sorting orders (e.g., ASCENDING, DESCENDING). The program should prompt the user to enter an array of integers and a sort order, sort the array according to the specified order, and print out the sorted array.
  9. Write a program that defines an enumerated type called file_mode, with values representing different modes for opening files (e.g., READ, WRITE, APPEND). The program should prompt the user to enter a file name and a mode, open the file in the specified mode, read or write data as appropriate, and print out any relevant information (e.g., the contents of the file if reading, or a success message if writing).
  10. Write a program that defines an enumerated type called error_codes, with values representing various errors that can occur in a software application (e.g., INVALID_INPUT, FILE_NOT_FOUND, MEMORY_ERROR). The program should prompt the user to enter an error code and print out a corresponding error message for each valid error code.

FAQ

  1. Why can't I use enumeration constants as array indices?
  • Enumeration constants have an underlying type of int, but arrays in C require that their indices be of type size_t. To work around this, you can cast the enumeration constant to size_t before using it as an index.
  1. Can I use bitwise operations on enumerations?
  • Yes, since enumerations are just a special kind of integer, you can perform bitwise operations on them. However, be aware that this might lead to unexpected results if the underlying type of your enumeration is not large enough to hold the resulting values.
  1. How do I compare enumeration constants for equality?
  • You can use regular comparison operators like == to compare enumeration constants for equality. However, keep in mind that the order of enumeration constants does not have to be sequential (e.g., you could define them as RED = 1, GREEN = 4, and BLUE = 2).
  1. Can I use enumerations with structures?
  • Yes, enumerations can be used as members of structures in C. This allows you to create custom data types that are more meaningful and easier to understand.
  1. How do I print out the names of enumeration constants instead of their values?
  • To print out the names of enumeration constants instead of their values, you can use a switch statement or a lookup table (array) that maps each enumeration constant to its corresponding name. For example:
const char* color_names[] = { "RED", "GREEN",