Foundations · Module 1 · Lesson 2 of 7
Repeating Yourself: for and while Loops
Learn how to repeat code with for and while loops, trace loop execution step by step, and avoid off-by-one errors and infinite loops.
By the end you can
- Write for loops to repeat code a known number of times
- Write while loops to repeat while a condition is true
- Trace loop iterations through variables and output
- Identify and fix off-by-one errors and infinite loops
Builds on Making Decisions: if, else if, and else.
01 · A question first
You need to print the numbers 1 through 100. You could write 100 printf statements, but that is slow and error-prone. What if you need 1,000 numbers? Or a million? How does the computer repeat an action without you writing it out every time?
Make a guess, then step through the trace below to check it.
02 · Watch it run
int sum = 0;for (int i = 1; i <= 5; i = i + 1) { sum = sum + i;}printf("%d\n", sum);- slot 0sum: 0(looked at in this step)
- slot 1i: 1(looked at in this step)
- slot 2iteration: 1
sum starts at 0, i starts at 1. The loop condition (i <= 5) is checked.
Machine work: init sum=0, i=1; check 1 <= 5 -> true
03 · The idea
Start with the problem
Suppose you need to print the numbers from 1 to 5, or add up every integer from 1 to 100. With only variables and printf, you would have to write the same statement over and over:
int sum = 1 + 2 + 3 + 4 + 5;Writing five additions by hand is tedious; writing 10,000 additions is impossible. Worse, what if the upper limit n is typed by the user at runtime via scanf? You cannot write n lines of code when you do not even know what n is until the program runs.
To process arbitrary amounts of data, a program needs iteration: a way to write a block of code once and instruct the CPU to repeat it as long as a condition holds. C provides two primary loop constructs for this: the for loop and the while loop.
How the idea works
Every loop needs three pieces of machinery to do useful work and stop on time:
- A starting state (initialization): Setting up a counter or accumulator variable before the first repetition begins.
- A continuation test (condition): A boolean check evaluated before each repetition. If the test is true (non-zero), the loop body runs; as soon as the test becomes false (
0), the loop terminates and execution continues on the line after the closing brace. - A progress step (update): Advancing the counter or state at the end of each repetition so the loop moves closer to stopping.
The for loop: counting a known number of times
When you know in advance how many iterations you want—such as counting from 1 to n or walking across n elements—the for loop puts all three pieces of loop control right at the top inside parentheses, separated by semicolons:
int sum = 0;
for (int i = 1; i <= 5; i = i + 1) {
sum = sum + i;
}
printf("Sum: %d", sum);Look at the trace above to see the exact order in which the CPU executes those three parts:
- Initialization (
int i = 1): Runs once when the loop is first entered. Along withsum = 0, this sets up step 1 of the trace. - Condition check (
i <= 5): Tested before every single iteration, including the very first one. Since1 <= 5is true, the CPU enters the loop body. - Loop body (
sum = sum + i;): Adds the current value ofiinto the accumulatorsum. - Update (
i = i + 1, often writteni++): Runs at the end of each iteration, right before jumping back to step 2 to re-testi <= 5.
In the trace above, i steps through 1, 2, 3, 4, and 5, accumulating sum values of 1, 3, 6, 10, and finally 15. After the fifth iteration adds 5, the update step increments i to 6. The condition 6 <= 5 evaluates to false (0), and the loop exits cleanly with sum == 15.
The while loop: repeating until an event happens
When you do not know in advance how many iterations will be needed—for example, dividing a number by 10 until no digits remain, or reading numbers from stdin until the user types 0—use a while loop:
int number = 4829;
int digits = 0;
while (number > 0) {
number = number / 10;
digits = digits + 1;
}
printf("Digits: %d", digits); /* prints 4 */A while loop has only the condition inside its parentheses. You write the initialization before the loop and the update inside the loop body. In fact, any for (init; cond; update) loop is equivalent to initializing first, testing while (cond), and running update at the bottom of the body.
Controlling loop flow early: break and continue
Sometimes you need to adjust a loop from inside its body:
breakexits the loop immediately, jumping to the first statement after the loop's closing brace (for example, stopping a search the moment you find the target value).continueskips the remaining lines of the current iteration and jumps straight to the update step (in aforloop) or condition test (in awhileloop).
Why it is correct
How do you convince yourself—and a code reviewer—that a loop computes the right answer and never gets stuck? Computer scientists reason about loops using two properties:
- The loop invariant: A statement about your variables that holds true before each iteration begins and after each iteration finishes. In the trace above, right before testing
i <= 5on every step,sumalways equals the sum of all integers from1up toi - 1. When the loop finally stops becauseihas reached6, the invariant guarantees thatsumholds the sum of integers from1to6 - 1 = 5. - Termination (progress toward the bound): Every iteration increases
iby1while the upper bound5stays fixed. Becauseistarts at1and strictly increases by1on every step,iis guaranteed to reach6after exactly 5 iterations, forcingi <= 5to become false.
What it costs
A loop executes its body once per iteration. If a loop runs from i = 1 to n and performs a constant number of basic operations (an addition, an increment, and a comparison) on each pass, its time complexity is proportional to n, written O(n).
- For
n = 5, the CPU executes 5 additions quickly. - For
n = 1,000,000, the CPU executes one million additions; the exact time depends on the compiler, processor, and surrounding work. - Meanwhile, the loop only ever uses two integer variables (
sumandi), so its space cost is constant—just 8 bytes of stack memory whethernis5or500,000,000.
Pitfalls and variations
| Mistake | What goes wrong | Fix |
|---|---|---|
for (int i = 0; i >= 0; i++) | Condition i >= 0 stays true as i grows, creating an infinite loop (until integer overflow) | Make sure the update moves i toward making the condition false (i < n) |
Forgetting to update the variable in a while loop | The variable tested in while (n > 0) never changes, freezing the program in an infinite loop | Update the loop variable on every path through the while body |
Uninitialized accumulator (int sum;) | sum = sum + i adds 1, 2, ... onto random stack garbage | Always initialize accumulators (int sum = 0; or int product = 1;) before the loop |
Using continue in a while loop before the update | Jumps back to the condition check and skips i++ at the bottom of the body, causing an infinite loop | Use a for loop (where continue still runs the update expression) or update before continue |
Where it is used
Loops drive almost every workload in computing: game engines run a while (running) loop 60 times per second to render frames, network servers loop continuously over incoming client requests, and data processing pipelines iterate over millions of array elements and file records.
In the next lesson, you will learn how to package loops and calculations into named functions so you can call them from anywhere in your program without repeating yourself.
04 · Prove it
Question 1 of 3 · answer from memory
What is the final value of sum after the trace above completes?
05 · Practice
Asked in interviews
Something wrong with this lesson? Report a problem