C Mastery / Control Flow: Iteration (while, do, for) and Jumps
Part 1 — The Core Language

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

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

StatementEffect
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

Undefined Behavior

constraint violation/UB in certain cases (c.arr.vla).

constraint violation.

Portability

the top of the block.

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

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.

References

Verification

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.flow.while05
c.flow.for05
c.flow.jump05