Loops

Course 1 · Ch 4
Loops
The three-part for loop Rust deliberately doesn't have

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

for (int i = 0; i < 5; i++) { printf("%d\n", i); }

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 (n > 0) { n--; } do { n--; } while (n > 0);

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.

// C89 style — still valid, sometimes seen in older code int i; for (i = 0; i < 5; i++) { /* ... */ }

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.

for (;;) { // runs forever, until an explicit break }
ConceptRustC
Counted loopfor i in 0..5for (int i = 0; i < 5; i++)
Check-after loopno dedicated keyworddo { ... } while (cond);
Infinite looploop { ... }for (;;) or while (1)
Prefer declaring the loop variable inside the for
C99-style 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.
do-while needs a trailing semicolon
} 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

Challenge 1

Write a for loop that prints the numbers 1 through 10, then rewrite the same logic using a while loop instead.

📄 View solution
Challenge 2

Write 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 solution
Challenge 3

Explain 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 solution

Chapter 4 Quick Reference

  • for (init; cond; incr) — Rust has no equivalent syntax, only range/iterator-based for
  • while — checks before; do-while — checks after, always runs at least once
  • break/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 dedicated loop keyword
  • do { ... } while (cond); — don't forget the trailing semicolon
  • Next chapter: functions — declarations, definitions, and pass-by-value by default