Skip to content
Informatics

Control structures in C: if, switch, while, do-while and for

Selection with if and switch, state machines, while, do-while and for loops, nested loops, break and continue, the microcontroller's endless loop and frequent mistakes.

A program that always executes the same statements in the same order is of little use. Control structures let you choose what to do depending on the data and repeat operations. They are the three structures of structured programming (sequence, selection, iteration) translated into C. In this lesson we cover if, switch, while, do-while and for, with typical examples and the most frequent mistakes.

Selection: if and else

if (temperature > 85) {
    fan_speed = 100;
    printf("Alarm: high temperature\n");
} else if (temperature > 60) {
    fan_speed = 70;
} else {
    fan_speed = 30;
}

The condition is an expression: if it is zero it is false, otherwise true. Braces can be omitted if the branch holds a single statement, but it is a dangerous habit: adding a second indented line makes it look part of the branch while it actually always runs. In 2014 a mistake of this kind (a duplicated goto fail; line) disabled SSL certificate verification in Apple’s systems.

The conditional operator. To choose a value compactly: maximum = (a > b) ? a : b;.

Multiple selection: switch

When choosing among many cases based on the integer value of an expression:

switch (command) {
    case 'A':
        led_on();
        break;
    case 'S':
        led_off();
        break;
    case 'L':
    case 'l':                 /* two cases sharing the same code */
        led_blink();
        break;
    default:
        printf("Unknown command: %c\n", command);
}

break leaves the switch. If it is missing, execution “falls through” into the next case: sometimes intended, as for ‘L’ and ‘l’, more often a bug. switch is the natural structure for state machines, used everywhere in firmware: a communication protocol, a device menu, a motor start-up sequence.

The while loop

It repeats a block while the condition is true; the condition is checked before each iteration, so the block may never run.

/* how many digits a positive integer has */
int n = 40527, digits = 0;
while (n > 0) {
    n /= 10;
    digits++;
}
/* digits is 5 */

The do-while loop

Like while, but the condition is checked after: the block runs at least once. It suits cases where something must be done before deciding whether to repeat it, such as asking for input until it is valid:

int choice;
do {
    printf("Choose a value between 1 and 5: ");
    scanf("%d", &choice);
} while (choice < 1 || choice > 5);

The for loop

It is the compact form for counter loops: initialisation, condition and update sit on one line.

/* average of n samples */
double sum = 0.0;
for (int i = 0; i < n; i++) {
    sum += samples[i];
}
double average = sum / n;

It is equivalent to a while with the initialisation before and the update at the end of the block. In C indices start at 0: an array of n elements goes from 0 to n - 1, so the condition is i < n, not i <= n. Being off by one is the most common bug of all.

Nested loops. For example the times table:

for (int r = 1; r <= 10; r++) {
    for (int c = 1; c <= 10; c++) {
        printf("%4d", r * c);
    }
    printf("\n");
}

The inner block runs 10\times 10 = 100 times. With two nested loops over n elements the cost is O(n^2): the reason bubble sort is slow.

break and continue

  • break leaves the innermost loop at once;
  • continue skips the rest of the current iteration and moves to the next.
/* find the first sample above threshold, ignoring invalid (negative) ones */
int found = -1;
for (int i = 0; i < n; i++) {
    if (samples[i] < 0) continue;
    if (samples[i] > threshold) { found = i; break; }
}

The microcontroller’s endless loop

A microcontroller program never ends: after initialisation it enters an infinite loop that reads inputs, updates the state and drives outputs.

int main(void)
{
    init_peripherals();
    for (;;) {               /* or while (1) */
        read_sensors();
        update_state();
        update_outputs();
    }
}

It is the structure Arduino hides behind its setup() and loop() functions.

Frequent mistakes

  • A semicolon after the condition: while (i < n); is an empty loop, infinite if i does not change.
  • Comparing reals with ==: after floating-point calculations 0.1 * 3 == 0.3 is false. Use a tolerance.
  • Changing a for counter inside the loop: it works, but it makes the code hard to follow.
  • Forgetting to update the condition variable in a while: an infinite loop.
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x
()
x