C Programming 3 min read

Control flow

if picks a branch, switch jumps to a matching case, and while, for and do repeat code. A forgotten break falls into the next case. Bare-metal firmware usually ends in a super-loop, for (;;), that never returns.

After power-on, the program initialises the hardware once, then reads its inputs. If an event is pending, it handles it and goes back to reading inputs. If not, it waits for the next interrupt and then reads the inputs again. The loop never ends.
A super-loop: read inputs, handle what happened, wait, and go round again.

Choosing a branch

if runs its block when the condition is non-zero, and else if chains test one condition after another. switch compares one integer value with constant case labels and jumps straight to the match, so it suits commands, states and message IDs. Execution then runs on until a break: stacking two labels on one action is useful, but a missing break silently runs the next case as well.

control.cC
#include <stdio.h>static const char *level(int adc) {    if (adc < 100) {        return "low";    } else if (adc < 900) {        return "ok";    } else {        return "high";    }}int main(void) {    const int samples[] = {42, 512, 1000};    for (int i = 0; i < 3; i++) {        printf("%4d %s\n", samples[i], level(samples[i]));    }    char cmd = 'R';    switch (cmd) {    case 'r':    case 'R':                 /* two labels, one action */        puts("reset");        break;    case 's':        puts("start");        break;    default:        puts("unknown command");        break;    }    int tries = 0;    do {        tries++;              /* runs at least once */    } while (tries < 3);    printf("tries = %d\n", tries);    return 0;}
Output
  42 low
 512 ok
1000 high
reset
tries = 3

Three loops

while tests before each pass, so its body may never run. for puts the start, the test and the step in one line, which suits counting. do ... while tests after the pass, so the body always runs at least once, for example one attempt before checking for a retry. break leaves a loop early, and continue skips to the next pass.

The super-loop

A bare-metal program has nowhere to return to, so after setting up the hardware, main enters an endless loop, written for (;;) or while (1). Each pass reads inputs, handles whatever happened, and then waits. Interrupts usually just set flags that the loop picks up on its next pass.