A loop repeats a block of instructions, which saves you copying and pasting the same code. C++ offers three forms of it: for (repeat a known number of times), while (repeat as long as a condition holds), and do…while (like while, but running at least once). This page presents all three, explains which one to choose, then warns about a point specific to embedded work: a waiting loop can freeze the whole program.
What is it for?
As soon as an action repeats (configuring 8 pins, sweeping an array of sensors, running an LED along a strip), the loop replaces a dozen repetitive lines with three. And beyond the saving in typing, it is the tool for going through data (an array of readings) or waiting for a condition. Picking the right form makes the intent readable: “I repeat N times” is not written the same way as “I repeat as long as”.
for — a known number of times
The form of choice when you know how many times to repeat. Three elements, separated by ;, between the parentheses:
for (int i = 0; i < 8; i++) { // init ; condition ; increment Serial.println(i); // prints 0, 1, 2, ... 7}
initialisation (int i = 0): run once, at the start;
condition (i < 8): tested before each pass, you carry on as long as it is true;
increment (i++): run at the end of each pass.
The variable i (the counter) exists only inside the loop (block scope, see local and global variables). This is the ideal form for going through an array by its indices.
while — as long as a condition holds
For when you do not know in advance how many times to repeat, but you do know until when:
while (analogRead(A0) < 500) { // as long as the reading is low // ... do something ...}
The condition is tested before each pass. If it is false from the outset, the block does not run at all (zero times).
do…while — at least once
Identical to while, with one difference: the condition is tested at the end. The block therefore always runs at least once, even if the condition is false from the start:
int valeur;do { valeur = analogRead(A0); // reads AT LEAST once} while (valeur < 100); // then goes again while it is too low
Useful when the action has to happen before you can test its result (reading a value before deciding whether it will do).
Which one to choose?
Form
When to use it
Number of runs
for
the number of repetitions is known in advance
0 or more (test at the start)
while
you repeat as long as a condition holds, count unknown
0 or more (test at the start)
do…while
it has to run at least once before testing
1 or more (test at the end)
In practice: for to go through or count, while to wait for a condition, do…while in the rarer case where the first run is unconditional. All three are interchangeable on paper. You pick the one that expresses the intent most clearly.
break and continue
Two keywords refine how a loop unfolds: breakinterrupts the loop immediately. continueskips to the next pass without finishing the current one.
for (int i = 0; i < 100; i++) { if (capteurDefaillant(i)) continue; // skip this sensor, move to the next if (urgence()) break; // stop straight away traiter(i);}
Warning
The real “infinite loop” of an embedded program is loop(). So you almost never write a while (true) by hand. Above all, a waiting loop (while (digitalRead(BOUTON) == HIGH) { }) freezes the whole program for as long as it runs: nothing else executes, the board looks stuck. That is acceptable for a very brief wait, but as soon as a system has to do several things “at the same time”, you do not wait inside a loop: you move to non-blocking programming.
Code to read
A running light: an LED travels along six pins, one after another, over and over. The sketch uses one for to configure the pins, and one for to sweep them — going through an array of indices.
const int LEDS[] = {2, 3, 4, 5, 6, 7}; // the six pins, in an arrayconst int NB_LEDS = 6;void setup() { for (int i = 0; i < NB_LEDS; i++) { // for: configure each pin pinMode(LEDS[i], OUTPUT); } Serial.begin(115200);}void loop() { for (int i = 0; i < NB_LEDS; i++) { // for: sweep the LEDs one by one digitalWrite(LEDS[i], HIGH); delay(100); digitalWrite(LEDS[i], LOW); }}
Without a loop, you would have had to write twelve digitalWrite calls and as many delay calls. The for goes through the LEDS array by its index i, from 0 to NB_LEDS - 1. Changing the number of LEDs only takes editing the array and NB_LEDS.
Pitfalls
An unintended infinite loop. If the condition of a while never becomes false (or if you forget to increment the counter of a for), the loop runs endlessly and the program freezes. Check that the condition will eventually become false.
Running past the end of an array. With an array of 6 slots (indices 0 to 5), for (int i = 0; i <= 6; i++) reaches slot 6, which does not exist: a memory read out of bounds, unpredictable behaviour. The correct condition is i < 6 (or i < NB_LEDS).
The fatal ; after the for.for (int i = 0; i < 10; i++);: the trailing semicolon makes an empty loop. The real block that follows runs only once, after the loop. Never put a ; right after the closing parenthesis of a for.
Waiting inside a blocking loop. See the box: a while used for waiting freezes everything. Keep it for very short waits; otherwise, non-blocking programming.
Exercises
Exercise 1 — Counting down
Using a for loop, print a countdown from 10 to 1 on the serial monitor, then the word "Go!".
Answer to exercise 1
void setup() { Serial.begin(115200); for (int i = 10; i >= 1; i--) { // from 10 down to 1, decrement Serial.println(i); delay(500); } Serial.println("Go!");}void loop() {}
The loop sits in setup() because the countdown must happen only once. The counter starts at 10, the condition i >= 1 stops it at 1, and i-- decrements it.
Exercise 2 — while or do…while?
What does each of these two loops do if, from the outset, the button is already released (digitalRead returns HIGH)? How do they differ?
A (while): the condition is tested first. Since the button is released (so == LOW is false), the block does not run at all — "A" is never printed.
B (do…while): the block runs once before the test. "B" is printed once, then the false condition stops the loop.
That is the whole difference: do…while guarantees at least one pass. (And a reminder: both of these waiting loops would freeze the program for as long as the button stayed pressed.)
Where it fits in the project
Step 4 of the proof of concept phase — sweeping a set of sensors or outputs, going through an array of readings: the for loop is the basic tool as soon as you handle several channels.
Non-blocking programming — the limit of blocking waiting loops leads straight to handling time without freezing the program, which becomes essential as soon as the system does several things at once.