C control structures: if, switch, while, for, do-while
Decision and loop structures, break/continue, fall-through in switch, common traps (= inside an if, the dangling else, ; after a for) and their counterpart in LC-3 branches.
In week 10 you built loops and ifs by hand with BR instructions. In C the same structures are written with keywords like if, while, for; the compiler translates them into the BR patterns you wrote. This page explains the rule of each structure and the points where the exam sets the most traps. The question type is again “What is printed?”.
if and if-else
int score = 72;
if (score >= 85) printf("AA\n");
else if (score >= 70) printf("BB\n");
else if (score >= 50) printf("CC\n");
else printf("FF\n");
BB
The conditions are tested from top to bottom, the block of the first true one runs, and the rest are skipped.
PITFALL ·
=versus==.if (x = 5)assigns 5 to x and the value of the expression is 5, always true. The compiler usually gives only a warning. When you see this code in the exam, write the output according to the assignment.
Dangling else
if (a == 0)
if (b == 0) printf("A\n");
else printf("B\n");
The indentation makes you think the else belongs to the outer if. The rule is not that: the else attaches to the nearest unmatched if. That is, it is the else of the inner if (b == 0). When a = 1 nothing is printed. To make your intent clear, always use { }.
switch
switch (expression) {
case CONST1: ... break;
case CONST2: ... break;
default: ...
}
Execution jumps to whichever case the value of the expression matches, and continues until a break (or until the switch ends). If there is no break, the code of the cases below also runs: fall-through.
int d = 1;
switch (d) {
case 0: printf("zero ");
case 1: printf("one ");
case 2: printf("two ");
}
one two
Case labels must be constants (int or char). You cannot write case x > 5:.
while
int n = 3;
while (n > 0) {
printf("%d ", n);
n--;
}
printf("go\n");
3 2 1 go
The condition is tested first. If it is false at the start, the body never runs.
The LC-3 counterpart (n in R0):
LOOP ADD R0, R0, #0 ; set the CC according to n
BRnz DONE ; exit if n <= 0
... ; body
ADD R0, R0, #-1 ; n--
BRnzp LOOP
DONE ...
for
for (init; condition; update) body;
It is the same as:
init;
while (condition) { body; update; }
int i;
for (i = 1; i <= 4; i++)
printf("%d ", i * i);
1 4 9 16
The trace table
Solve loop questions with a table:
for (i = 10; i > 0; i /= 2) c++;
i i > 0? c
10 yes 1
5 yes 2
2 yes 3
1 yes 4
0 no (ends)
PITFALL · a semicolon after the for.
for (i = 0; i < 5; i++);is a loop with an empty body. The line below, whatever its indentation, runs once after the loop ends and sees i = 5.
do-while
do {
body;
} while (condition);
The body runs first, the condition is tested afterwards. So it runs at least once. It is ideal for menu loops (“ask until the user enters 0”). The ; at the end is required.
break and continue
break: leave the innermost loop or switch immediately.continue: skip the rest of this round and move on to the next one. In a for, the update part (i++) still runs.
for (i = 0; i < 10; i++) {
if (i % 3 == 0) continue; /* 0, 3, 6 are skipped */
if (i > 7) break; /* leave at 8 */
printf("%d ", i);
}
1 2 4 5 7
Nested loops
In each round of the outer loop, the inner loop runs from start to end.
int i, j;
for (i = 1; i <= 3; i++) {
for (j = 0; j < i; j++)
printf("*");
printf("\n");
}
*
**
***
The total number of inner rounds: 1 + 2 + 3 = 6. In “how many times does it run?” questions, write down how many times the inner loop runs for each outer round and add them up.
Worked trace: the Collatz sequence
If n is even halve it, if odd make it 3n + 1; continue until you reach 1.
int n = 6, steps = 0;
while (n != 1) {
if (n % 2 == 0) n = n / 2;
else n = 3 * n + 1;
printf("%d ", n);
steps++;
}
printf("\n%d\n", steps);
3 10 5 16 8 4 2 1
8
When building the trace table, write three things on each row: the result of the condition, which branch ran, and the new values of the variables.
n n != 1? branch new n steps
6 yes even 3 1
3 yes odd 10 2
10 yes even 5 3
5 yes odd 16 4
16 yes even 8 5
8 yes even 4 6
4 yes even 2 7
2 yes even 1 8
1 no (ends)
The LC-3 counterpart of the for loop
int s = 0, i;
for (i = 1; i <= 4; i++) s += i; /* s = 10 */
The compiler (s in R0, i in R1) produces roughly this:
AND R0, R0, #0 ; s = 0
AND R1, R1, #0
ADD R1, R1, #1 ; i = 1 (init)
LOOP ADD R2, R1, #-5 ; i - 5
BRzp DONE ; exit if i >= 5 (the opposite of the condition)
ADD R0, R0, R1 ; s += i (body)
ADD R1, R1, #1 ; i++ (update)
BRnzp LOOP
DONE HALT
In the simulator the result is R0 = 10, R1 = 5. The test i <= 4 turns into the question “is i - 5 negative?”: in the LC-3 a comparison always means a subtraction + the condition codes. If the condition is true it falls into the body; if false (z or p) it jumps out of the loop.
Ready-made loop patterns
| Job | Pattern |
|---|---|
| Sum from 1 to n | for (i = 1; i <= n; i++) s += i; |
| Digit sum | while (n > 0) { s += n % 10; n /= 10; } |
| Number of digits | while (n > 0) { c++; n /= 10; } |
| Read with a sentinel | while (x != 0) { ...; scanf("%d", &x); } |
| Ask at least once | do { ... } while (answer != 0); |
Common mistakes
| Wrong idea | The truth |
|---|---|
if (x = 5) compares x with 5 | It assigns; always true |
| else attaches by indentation | It attaches to the nearest if |
| switch runs the matching case and leaves | Without break it falls into the ones below |
| do-while never runs if the condition is false | It runs at least once |
The line after for (...); is in the loop | The loop is empty, the line runs once |
| continue ends the loop | It only skips this round |
| break leaves all nested loops | Only the innermost |
case x > 5: is valid | A case must be a constant |
Test yourself
Exam-style questions. Solve them on paper first, then reveal the answer.
What is printed?
int x = 0;
if (x = 5) printf("yes %d\n", x);
else printf("no %d\n", x);Show answer
x = 5 is an assignment, not a comparison. 5 is written into x and the value of the expression is 5; since 5 is not zero, it is true. A comparison needs ==.
What is printed?
int a = 1, b = 0;
if (a == 0)
if (b == 0) printf("A\n");
else printf("B\n");
printf("end\n");Show answer
The else attaches not to the indentation but to the nearest unmatched if (dangling else): it is the else of if (b == 0). Because the outer if (a == 0) is false, the inner if-else never runs. Only end is printed.
What is printed?
int i = 1, s = 0;
while (i <= 10) {
s += i;
i += 3;
}
printf("%d %d\n", s, i);Show answer
The body runs for i = 1, 4, 7, 10: s = 1 + 4 + 7 + 10 = 22. Then i = 13, the condition is false.
What is printed?
int i;
for (i = 2; i < 15; i += 4)
printf("%d ", i);Show answer
The condition is true for i = 2, 6, 10, 14. It ends when i = 18.
What is printed?
int n = 10;
do {
printf("%d ", n);
n++;
} while (n < 5);Show answer
do-while tests the condition AFTER the body, so the body runs at least once. 10 is printed, n = 11, 11 < 5 is false, the loop ends.
What is printed?
int k = 2;
switch (k) {
case 1: printf("one ");
case 2: printf("two ");
case 3: printf("three ");
break;
default: printf("other ");
}Show answer
It jumps to case 2. Because there is no break, it falls into the next case (fall-through) and three is printed too. At break the switch ends, default does not run.
What is printed?
int i;
for (i = 0; i < 10; i++) {
if (i % 3 == 0) continue;
if (i > 7) break;
printf("%d ", i);
}Show answer
continue skips the rest of that round (i = 0, 3, 6). break ends the loop: at i = 8, 8 % 3 ≠ 0, 8 > 7 → break. What is printed is 1 2 4 5 7.
What is printed?
int i, j, c = 0;
for (i = 0; i < 4; i++)
for (j = i; j < 4; j++)
c++;
printf("%d\n", c);Show answer
The inner loop runs 4 times for i = 0, 3 times for i = 1, 2 times for i = 2, 1 time for i = 3: 4 + 3 + 2 + 1 = 10.
What is printed?
int i;
for (i = 0; i < 5; i++);
printf("%d\n", i);Show answer
The ; at the end of the for is an empty body. The loop spins 5 times doing nothing, and i = 5. Despite the indentation, the printf is outside the loop and runs once.
How many times does the loop body execute, and what is printed?
int i, c = 0;
for (i = 10; i > 0; i /= 2)
c++;
printf("%d\n", c);Show answer
The body runs for i = 10, 5, 2, 1 (integer division: 5 / 2 = 2, 1 / 2 = 0). It ends when i = 0.
What is printed?
int n = 4096, s = 0;
while (n > 0) {
s += n % 10;
n /= 10;
}
printf("%d\n", s);Show answer
Digit sum: n % 10 takes the last digit, n / 10 drops it. 6 + 9 + 0 + 4 = 19.
A C compiler translates if (x < 0) x = -x; for the LC-3, with x already loaded into R0. Which branch instruction skips the assignment?
Show answer
The pattern: skip with the opposite of the condition. If x < 0 is not true (that is x ≥ 0, z or p), the assignment must be skipped: BRzp SKIP. After that, NOT R0, R0 / ADD R0, R0, #1 / STR updates x. The same as the absolute value program in week 8.
Verification: Every code snippet was compiled and run as C99 with Zig cc (clang), and the outputs were copied exactly (verify/SEN2201/c/w11b.c and w11c.c, node verify/SEN2201/c/run.mjs w11); the LC-3 counterpart of the for loop was run on our own simulator (end of verify/SEN2201/08.mjs).