Loops
Loops are one of the few places C's syntax and Rust's genuinely diverge in shape, not just in guarantees. This chapter covers all three C loop forms and where each one's closest Rust equivalent actually is.
The Three-Part for Loop
Init, condition, and increment, all in the parentheses. Rust has no equivalent syntax at all — Rust's own for only ever iterates over a range or an iterator (for i in 0..5), never a raw three-part counter. C's version is lower-level: nothing stops the counter, the bound, or the step from being anything at all.
while and do-while
while checks its condition before the first iteration — the body might never run. do-while checks after — the body always runs at least once. Rust has no do-while construct at all; the closest equivalent is a plain loop { ... if !condition { break; } }, spelled out manually rather than given its own keyword.
break and continue
Same meaning as in Rust — break exits the loop immediately, continue skips straight to the next iteration.
Loop Variable Scope: C89 vs. C99
Genuinely older C (C89) required loop counters to be declared before the loop, since variable declarations had to appear at the top of a block — for (int i = ...) wasn't legal syntax at all. C99 relaxed this, allowing the now-familiar in-loop declaration. Legacy C codebases still sometimes show the older style; recognizing it matters when reading real, older C.
Infinite Loops
C has no dedicated keyword for "loop forever" — the idiom is for (;;) or while (1), both relying on an empty or always-true condition. Rust's loop keyword states the same intent explicitly and self-documentingly, rather than as a side effect of an empty condition.
| Concept | Rust | C |
|---|---|---|
| Counted loop | for i in 0..5 | for (int i = 0; i < 5; i++) |
| Check-after loop | no dedicated keyword | do { ... } while (cond); |
| Infinite loop | loop { ... } | for (;;) or while (1) |
for (int i = 0; ...) keeps the counter's scope tightly bound to where it's actually used — simply better practice in new code, even though the older C89 style remains valid and appears in legacy codebases.
} while (cond); — the semicolon after the closing parenthesis is required and easy to forget, since no other block-ending construct in C needs one.
Coding Challenges
Write a for loop that prints the numbers 1 through 10, then rewrite the same logic using a while loop instead.
📄 View solutionWrite a do-while loop that runs its body at least once even though its condition is false from the start, printing a message that proves it ran. Explain why a plain while loop couldn't do this.
📄 View solutionExplain why C's for (;;) idiom for an infinite loop is a side effect of the loop's general syntax, while Rust's loop keyword is a dedicated, self-documenting construct — and what that difference reflects about each language's design philosophy.
📄 View solutionChapter 4 Quick Reference
for (init; cond; incr)— Rust has no equivalent syntax, only range/iterator-basedforwhile— checks before;do-while— checks after, always runs at least oncebreak/continue— same meaning as Rust- C89 required loop variables declared before the loop; C99 allows in-loop declaration
for (;;)/while (1)— C's infinite-loop idiom, vs. Rust's dedicatedloopkeyworddo { ... } while (cond);— don't forget the trailing semicolon- Next chapter: functions — declarations, definitions, and pass-by-value by default