Control Flow: Iteration (while, do, for) and Jumps
This chapter covers the iteration statements (while, do while, for) and the jump statements (break, continue, goto, return). It also explains the idiomatic patterns and the (few) places where goto is justified.
Why This Matters
Loops are the core of imperative programming, and goto — despite its reputation — is the cleanest tool for certain error-cleanup patterns in C. You need to know both the common forms and the disciplined exceptions.
Prerequisites
c.core.15— selection.
Core Concept
while
while (condition)
statement;
Tests the condition first; executes the body zero or more times.
do while
do
statement;
while (condition);
Executes the body at least once, then tests.
for
for (init; condition; increment)
statement;
Equivalent to:
init;
while (condition) {
statement;
increment;
}
with special handling for continue and omitted clauses.
Jump statements
| Statement | Effect |
|---|---|
break; | exits the nearest enclosing loop or switch |
continue; | jumps to the next iteration of the nearest loop |
goto label; | jumps to the labeled statement in the same function |
return expr; | returns from the current function |
Syntax
while (x > 0) x--;
do {
/* ... */
} while (x > 0);
for (int i = 0; i < n; i++) { /* C99 allows declaration in init */
/* ... */
}
goto cleanup;
cleanup:
/* ... */
Examples
for loop with declaration (C99)
#include <stdio.h>
int main(void)
{
int sum = 0;
for (int i = 1; i <= 10; i++) {
sum += i;
}
printf("%d\n", sum);
return 0;
}
Expected output: 55.
continue in for vs. while
In a for loop, continue still runs the increment clause. In a while loop, continue jumps straight to the condition test, so you must advance the loop variable yourself.
for (int i = 0; i < 5; i++) {
if (i == 2) continue; /* i++ still runs */
printf("%d\n", i);
}
/* prints 0 1 3 4 */
goto cleanup (idiomatic error handling)
int process(void)
{
FILE *f = fopen("data.txt", "r");
if (!f) return -1;
char *buf = malloc(1024);
if (!buf) goto cleanup_file;
/* ... use buf ... */
free(buf);
cleanup_file:
fclose(f);
return 0;
}
goto jumps *forward* to a cleanup label, avoiding duplicated cleanup logic.
How It Works
Loops compile to conditional branches at the top (while, for) or bottom (do while). break and continue compile to jumps. goto is a direct jump. The compiler may then optimize loops (unrolling, vectorization) subject to preserving observable behavior.
Variations
Infinite loops
for (;;) { /* ... */ }
while (1) { /* ... */ }
Both are idiomatic infinite loops; for (;;) avoids any "condition is constant" warnings.
Omitting for clauses
Any of the three for clauses may be omitted; the semicolons remain.
Common Mistakes
- Forgetting that
continuein awhileloop skips the increment. - Writing
while (x = 5)instead ofwhile (x == 5). - Using
gototo jump backwards or into a block with a VLA. - Off-by-one errors in loop bounds.
Undefined Behavior
- Jumping with
gotointo the scope of a variable-length array is a
constraint violation/UB in certain cases (c.arr.vla).
- A
returnwith a value from avoidfunction (or vice versa) is a
constraint violation.
Portability
for (int i = 0; ...)requires C99 or later; C89 required declarations at
the top of the block.
- All loop and jump constructs are ISO C and fully portable.
Under the Hood
The compiler may unroll loops, eliminate the loop variable, or vectorize the body. These transformations are legal because they preserve observable behavior (assuming no UB). goto cleanup patterns are usually compiled as plain jumps.
Practical Usage
- Prefer
forwhen the iteration count is known or driven by a counter. - Prefer
whilewhen the termination is data-dependent. - Prefer
do whilewhen the body must run at least once. - Use
gotoonly for forward cleanup jumps, and keep it structured.
Exercises
1. Write each of for, while, and do while loops that compute the sum of 1..N and compare their structure. 2. Demonstrate the continue difference between for and while. 3. Write a function with multiple resources and a goto cleanup pattern, then rewrite it without goto and compare readability.
Deep Challenge
Implement a function that reads lines from a file until EOF, and discuss the cleanest loop structure for the "read, check EOF, process" pattern. Justify why while ((n = read(...)) > 0) or for (;;) { ... break; } is preferable in different situations.
Related Concepts
c.flow.if— selection.c.stdlib.2— file I/O (used in the deep challenge).c.core.17— functions and return.
References
- ISO/IEC 9899:2018 §6.8.5 (iteration), §6.8.6 (jump statements).
Verification
for/while/do whilesemantics are standard.VERIFIEDcontinuebehavior inforvswhile.VERIFIEDgotocleanup is idiomatic.VERIFIED- No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] while
- [ ] do while
- [ ] for
- [ ] break and continue
- [ ] goto and labels
- [ ] return
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.flow.while | 0 | 5 |
| c.flow.for | 0 | 5 |
| c.flow.jump | 0 | 5 |