🌱 C Basics
for loops: init, test, step — all in one line
▶ Open the interactive lesson — free, no signupPrint 100 scores, check every character of a password, draw each row of a game board — "do this N times" is the single most common instruction in programming. The for loop packs the whole job into one line, and this lesson also arms you against the off-by-one mistake that has haunted every programmer who ever lived.
Last lesson's healthy-loop checklist — initialize, test, update — is so universal that C gives it a shorthand of its own. The for loop puts all three on one line, where you can't forget any of them:
#include <stdio.h>
int main(void) {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
printf("1 + 2 + ... + 100 = %d\n", sum);
return 0;
}$ gcc sum100.c -o sum100 && ./sum100 1 + 2 + ... + 100 = 5050 # young Gauss computed this in his head; your CPU does it in nanoseconds
for (init; condition; step) runs like this — note it's exactly a while loop in a tailored suit:
▶ This spot has an interactive flow widget — open the interactive lesson to play with it.
- init runs once, before anything else. Declaring the variable right there (
int i = 1) is standard since C99. - condition is tested before every iteration — first one included.
- step runs after each body, just before the next test.
Watch all three phases fire in order:
▶ This spot has an interactive trace widget — open the interactive lesson to play with it.
🧠 Checkpoint: In for (int i = 0; i < 5; i++), when does i++ run?
- Before the body, each time
- After the body, before the next condition check
- Once, at the very end of the loop
- Whenever i is used
Show answer
After the body, before the next condition check — Order per iteration: test → body → step → test again. The step always runs after a completed body — that’s why the trace showed i changing right before each new test.
The loop variable's tiny life
Declare i in the init clause and it exists only inside the loop — after the closing brace, i is gone, and mentioning it is a compile error. This is a feature: each loop gets a fresh, private counter, and no stale counters leak around your function.
Off-by-one, the eternal enemy: for (int i = 0; i < n; i++) runs exactly n times — the idiomatic C loop (and it will match array indexing perfectly in Part 2). Writing <= runs n+1 times. When a loop misbehaves, check the boundary first: does it start at 0 or 1? Is the test < or <=?
🧠 Checkpoint: How many times does for (int i = 0; i <= 10; i += 2) run its body?
- 5
- 10
- 6
- 11
Show answer
6 — i takes 0, 2, 4, 6, 8, 10 — six values (the <= keeps 10 in). With < it would be five. Counting fence posts carefully is half of C programming.
Nested loops: the times table
A loop body can contain another loop. The inner loop runs to completion for every single iteration of the outer one — 10 × 10 = 100 inner bodies here:
#include <stdio.h>
int main(void) {
for (int row = 1; row <= 10; row++) {
for (int col = 1; col <= 10; col++) {
printf("%4d", row * col);
}
printf("\n"); /* end the row */
}
return 0;
}$ gcc timestable.c -o tt && ./tt 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100 # %4d right-aligns each number in 4 columns — instant neat table
Two counters at once: the comma operator
The init and step clauses each accept only one expression — but the comma operator chains several into one, evaluating left to right. It's the idiomatic way to walk two indices together (you'll meet it again reversing arrays in Part 2):
#include <stdio.h>
int main(void) {
/* two counters marching toward each other */
for (int lo = 0, hi = 9; lo < hi; lo++, hi--) {
printf("lo=%d hi=%d\n", lo, hi);
}
return 0;
}$ gcc comma.c -o comma && ./comma lo=0 hi=9 lo=1 hi=8 lo=2 hi=7 lo=3 hi=6 lo=4 hi=5
All three clauses are optional. for (;;) — affectionately "forever" — is a perfectly legal infinite loop, equivalent to while (1). The semicolons stay, though: for () won't compile.
▶ This spot has an interactive editor widget — open the interactive lesson to play with it.
🧠 Checkpoint: After for (int i = 0; i < 3; i++) { }, what does printf("%d", i); do?
- Prints 3
- Prints 2
- Compile error — i no longer exists
- Prints garbage
Show answer
Compile error — i no longer exists — A variable declared in the init clause is scoped to the loop. After the closing brace it’s not garbage — it’s GONE, and the compiler rejects the name outright. Declare i before the for if you need its final value.
You can now start loops — next you'll learn to escape them early: break, continue, and the infamous goto.
▶ Practice this lesson interactively (with live gcc)