Visual walkthrough — Enumerations
This is the parent topic taken apart slowly. Every symbol here is earned before use. If you have never seen an enum, start at line one — nothing is assumed.
Step 1 — A name is really just a locker number
WHAT. We line up three empty lockers and stick a paper name-tag on each: RED, GREEN, BLUE. The machine does not read tags; it only reads locker numbers. Our whole job is to work out which number hides behind each name.
WHY. Before any rule, you must believe the core secret: in C an enumerator is not a special object — it is literally an integer wearing a name-tag. This is the foundation the parent note calls "sticky notes on lockers". Everything else is bookkeeping about which number lands on which tag.
PICTURE. Three grey lockers, one blue name-tag each. The number inside the locker is what we are hunting.

Step 2 — The first tag always gets 0
WHAT. We fill in the very first locker. The C rule: the first enumerator with no number written next to it gets the value .
- — the 0th (first) enumerator in the list. We count from 0 because C counts from 0.
- — its hidden integer.
- — the starting value, chosen by the language so it lines up neatly with array indices later.
WHY 0 and not 1? Because C arrays start at index 0 (see Arrays in C). If enums also start at 0, an enumerator can be used directly as an array position with no "+1" fudge. That design choice is the reason for this exact number.
PICTURE. The RED locker fills with a bold 0.

Step 3 — Every next tag is "previous + 1"
WHAT. For every enumerator after the first that has no explicit number, we compute it by taking the previous one and adding 1:
- — the enumerator at position (the one we are filling now).
- — the enumerator immediately before it in the written list.
- — take that neighbour's number and step up by one.
WHY this tool — a recurrence? A recurrence is a rule that defines each term using the term before it. We choose it because the C standard literally says "one greater than the previous enumerator". It answers the question "if I only know 0 and the phrase 'add one', can I generate the whole list?" — yes: apply the rule repeatedly.
Applying it to {RED, GREEN, BLUE}:
PICTURE. Orange "+1" arrows hop locker-to-locker: 0 → 1 → 2.

Step 4 — Writing an explicit number teleports the counter
WHAT. You may pin a number to any tag with =. That number overrides the "+1" for that tag only:
enum Status { OK = 1, WARN = 5, ERR, FATAL = 5 };OK = 1— explicit, so (the teleport ignores 0).WARN = 5— explicit again, teleport to 5.ERR— no number, so the +1 rule wakes up: .FATAL = 5— explicit, teleport back down to 5.
WHY does the +1 rule "resume" after a jump? Because the recurrence in Step 3 never says "add 1 to the previous default" — it says "add 1 to the previous value", whatever that value was, jumped or not. So after WARN=5, the next default is simply .
PICTURE. A number line. Blue explicit landings (1, 5, 5) with teleport arrows; an orange "+1" hop produces ERR = 6.

Step 5 — Edge case: duplicate values are allowed
WHAT. In Step 4, both WARN and FATAL hold 5. That is completely legal.
WHY it must be legal. The rule only ever produces or copies integers, and integers repeat freely. The language only forbids two tags with the same name — because tags are looked up by name (see Step 7). Two different names can point at the same number, just like two people can live at the same house number.
PICTURE. Two distinct tags WARN and FATAL both pointing at the single value 5.

Step 6 — Edge case: the trailing COUNT sentinel
WHAT. Put an un-numbered tag last and it automatically equals how many tags came before it:
enum { JAN, FEB, MAR, MONTH_COUNT }; // MONTH_COUNT = 3WHY it works — chase the recurrence. JAN=0, FEB=1, MAR=2. The trailing tag is just "previous + 1" . But there were exactly 3 real months (JAN, FEB, MAR at positions 0,1,2), so the last value is the count. This is not a special feature — it is Step 3 falling out for free. Add a month and the count updates by itself, which is why it sizes an array safely.
PICTURE. Three data lockers 0,1,2 and a separate green MONTH_COUNT = 3 measuring the whole row like a ruler.

Step 7 — Degenerate case: at runtime the names vanish
WHAT. After compilation, the tags are gone. Only integers remain. So:
enum Color { RED, GREEN, BLUE };
printf("%d\n", GREEN); // prints 1, NOT "GREEN"WHY. The name-tags of Step 1 are a compile-time convenience. The compiler swaps every GREEN for 1 and then throws the tags away. There is no name table left to look up — unlike some languages, C keeps no reverse map. To recover names you must build your own array of strings (an idea linked to Integer Types in C, since the stored thing is a plain int):
const char *names[] = { "RED", "GREEN", "BLUE" };
printf("%s\n", names[GREEN]); // now prints "GREEN"PICTURE. Left: compile time, tags visible. Right: runtime, tags peeled off, only bare integers 0 1 2 survive.

The one-picture summary
Everything above is a single machine: seed with 0, walk with +1, teleport on =, names die at runtime.

Recall Feynman: retell the whole walkthrough in plain words
Picture a row of lockers. The first one, if you say nothing, gets number 0. Each locker after it copies its left neighbour's number and adds 1 — that's the entire counting rule. If you scribble a number on a locker with =, it jumps to that number, and the next un-numbered locker just keeps adding 1 from there (so 5 becomes 6). Two lockers are allowed to share a number; only the paper name-tags have to be different, because that's how the compiler finds them. A clever trick: an un-numbered tag placed last ends up equal to how many lockers came before, so it counts them for you. And the big secret: once the program actually runs, all the paper tags are peeled off and thrown away — the machine only ever sees the numbers, which is why printing GREEN gives you 1, not the word.
Connections
- Enumerations — the parent topic this walkthrough derives.
- Integer Types in C — the enumerator's hidden value is a plain
int. - switch statement — where these derived values are matched by name.
- Arrays in C — the
COUNTsentinel from Step 6 sizes arrays. - struct in C — groups data; enums instead name values.
- typedef —
typedef enum {...} Color;drops theenumkeyword.