Enumerations
enum for naming a set of related integer constants: numbering from zero, explicit values, why an enum constant is just an int, and the compile-time constant C otherwise lacks.
A Set of Names, Numbered For You
Programs are full of small fixed sets: the days of the week, the states a connection can be in, the options on a menu. Written as bare numbers they turn code into a puzzle, because if (state == 2) says nothing about what 2 means. The last lesson gave you #define for naming a single value, and you could certainly write seven of them for the seven days. But nothing then records that those seven names belong together, and you get to do the numbering by hand.
An enumeration solves exactly this shape of problem: it declares a type whose values are a named set, and numbers them for you.
Declaring an Enumeration
The declaration lists the names in braces:
enum weekday { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY };
Two separate things now exist. The first is a type, whose name is enum weekday — both words, always. The bare word weekday is not a type in C, and writing weekday today; is an error rather than a shortcut. (If you have met C++, this is one of the places the two languages genuinely differ, and later you will meet typedef, which is how C programmers buy themselves the shorter name.) The second is five enumeration constants, MONDAY through FRIDAY, which are ordinary integer constants usable anywhere a number is.
Declaring a variable of the type looks like any other declaration:
enum weekday today = WEDNESDAY;
The Numbering Rule
Left to itself, the compiler numbers the constants from zero, in the order you wrote them, each one more than the last:
MONDAY = 0
FRIDAY = 4
today = 2
Zero-based numbering is the detail exam questions are built on. MONDAY is 0, not 1, and the fifth name is 4. Notice also that %d prints an enumeration value, because what is stored is an integer.
Setting Values Yourself
Any constant in the list may be given an explicit value with =, and counting resumes from there:
STATUS_OK = 1
STATUS_WARNING = 2
STATUS_ERROR = 10
STATUS_FATAL = 11
STATUS_WARNING follows the 1 it was given and becomes 2; STATUS_FATAL follows the 10 and becomes 11. The rule is simply "one more than the previous constant, whatever set that one". This is how you match numbers a protocol or a file format has already chosen for you, and it is why enum status { A = 1, B = 1 }; is legal: nothing requires the values to be distinct.
Declaring the Type and Variables Together
The list and a variable declaration can be combined into one statement, which is common in older code and in textbooks:
enum weekday { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY } today, tomorrow;
That declares the type and the two variables today and tomorrow at once. If you never need the type name again, you may leave the tag out entirely:
enum { SCREEN_WIDTH = 80, SCREEN_HEIGHT = 25 };
This declares no variables and no reusable type name. What it does declare is two integer constants, and that turns out to be one of the most useful things an enumeration can do in C.
An Enum Constant Is Just an int
Here is the part that separates knowing the syntax from understanding it. In C, an enumeration constant has type int, and an enumeration variable has whatever integer type the implementation finds convenient. There is no separate, protected, scoped enumeration type in this language; that is C++'s enum class, which does not exist here. The practical consequence is that C does not check the value:
today = 4
nonsense = 99
sizeof(enum weekday) = 4
99 is not a weekday, and the compiler said nothing at all, warnings and pedantic mode included. So an enumeration is documentation the compiler helps you write, not a guarantee it enforces. Treat a value arriving from outside your program as an ordinary integer that needs checking, and when you eventually write a switch over an enumeration, give it a default branch for the value that should not be possible.
Two smaller facts belong here. Enumeration constants are constants, not variables: they have no address and cannot be assigned to, so MONDAY = 7; is an error. And sizeof reports 4 above only because this implementation chose int; the standard lets it choose any integer type that fits the values.
The Compile-Time Constant C Otherwise Lacks
The previous lesson left a promise open. A const variable in C is still a variable, so the contexts that demand a genuine constant expression will not take one, and array sizes are the case you meet first. #define works there because the substitution happens before the compiler sees the array. An enumeration constant also works there, and it is what most C programmers reach for:
enum { MAX_STUDENTS = 50 };
That is a real constant expression, typed int, produced by the compiler rather than by textual substitution, and visible under its own name in a debugger. Arrays arrive in chapter 7, and this is the form to use when you need to size one; the preprocessor's traps, which chapter 14 catalogues, are all avoided because no preprocessor is involved.
The rule of thumb for integers is therefore short: a set of related values, or a single integer constant, wants an enum. Reach for #define when the value is not an integer, as with #define PI 3.14159, since enumerations hold integers only.
Naming, and One Syntax Trap
Enumeration constants do not get a namespace of their own; they sit in the scope that encloses the declaration, exactly as a variable would. Two enumerations in one file that both offer RED will collide. The convention that avoids this is to prefix every constant with the set's name, which is why the examples above say STATUS_OK rather than OK, in the upper-case style C uses for constants generally.
The trap is a comma. A list may not end with one in this dialect:
enum color { COLOR_RED, COLOR_GREEN, };
A trailing comma was made legal in C99 and is harmless in modern code, but under the C89 rules this course compiles with, the compiler rejects it:
error: comma at end of enumerator list
If you meet that message, delete the comma before the closing brace.
Key Takeaways
- An enumeration declares a type whose values are a named set:
enum weekday { MONDAY, ... };declares the typeenum weekday, both words, plus the constants. - Constants number from zero upward by default, in declaration order.
- An explicit
= valuesets one constant and the next continues from it; values need not be distinct. - The type and variables may be declared together, and a tagless
enum { NAME = value };declares constants and nothing else. - Enumeration constants have type
intand C checks nothing: any integer may be stored in an enumeration variable, so aswitchover one still needs adefault. enum { MAX_STUDENTS = 50 };is the idiomatic C integer constant for places that demand a constant expression, such as array sizes, where aconstvariable is not accepted.- Prefix constants with the set's name to avoid collisions; a trailing comma in the list is a C99 relaxation that C89 rejects.
How did you find this lesson?
Your rating helps us improve the content.
Create an account to track your progress and access interactive exercises. Already have one? Sign in.
Enumerations - Quiz
Test your understanding of the lesson.
Practice Exercises
Season Codes and a Count
Declare enum season with the four seasons in order, spring first, followed by a final SEASON_COUNT marker. Print each season's value one per line, then the number of seasons taken from the marker, then the value of a variable of the enum type initialized to autumn. Let the automatic numbering produce every number: do not type the values yourself.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!