A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
An enum is a set of named integer constants. That is the honest description. The compiler treats enum values as ints. You can assign any integer to an enum variable. You can pass an enum where an int is expected. There is no type safety beyond what your discipline provides. What enum gives you is a namespace for related constants and automatic sequential numbering.
#include <stdio.h>typedef enum {SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY} Day;typedef enum {HTTP_OK = 200,HTTP_NOT_FOUND = 404,HTTP_SERVER_ERROR = 500} HttpStatus;int main(void) {Day today = WEDNESDAY;HttpStatus status = HTTP_NOT_FOUND;printf("today = %d\n", today);printf("status = %d\n", status);return 0;}
SUNDAY is 0, MONDAY is 1, and so on. The compiler auto-increments from the last explicit value. HTTP_OK starts at 200, so HTTP_NOT_FOUND is 404 only because we specified it. If we had omitted the explicit values, they would have been 200, 201, 202. Always specify values when the numbers carry semantic meaning, as with protocol codes.
#include <stdio.h>typedef enum { RED, GREEN, BLUE } Color;const char *color_name(Color c) {switch (c) {case RED: return "red";case GREEN: return "green";case BLUE: return "blue";}return "unknown";}int main(void) {printf("%s\n", color_name(GREEN));printf("%s\n", color_name(99));return 0;}
With -Wswitch, GCC warns if your switch over an enum type is missing a case. That is genuinely useful. It catches the bug where you add a new enum value but forget to handle it in every switch. The 99 argument compiles fine because enum is just int underneath. The function handles it via the default path. No crash, but no type enforcement either.
You can write Color c = 742; and it compiles. You can write if (RED == 0) and it works. You can pass an enum to printf with %d and get the integer. None of this is a bug in the compiler. C enums are not like enums in Rust or Swift. They are convenience wrappers around integer constants with a shared namespace. Treat them as documentation with compiler-assisted switch checking, not as a type barrier.
enums are the right tool for state machines, error codes, configuration options, and any closed set of named integers. They make code self-documenting and give the compiler a chance to warn you about missing cases. Next: how C handles boolean truth, which is stranger than you expect if you are arriving from a language with a real boolean type.
Finish the lesson once you have worked through the material. This awards ★ 20 XP.