07 Beginner The Hundred
The Loop That Never Ends
a four-step countdown with remarkable stamina
#include <iostream>
int main() {
int safety = 6; // more than enough for four lines... right?
for (unsigned i = 3; i >= 0; --i) {
std::cout << i << '\n';
if (--safety == 0)
break;
}
}
Run it. How many lines does it print?
Answer
Six: 3 2 1 0 4294967295 4294967294 — and only because the safety counter pulls the
plug. On its own, this loop runs forever.
Why¶
i is unsigned, and an unsigned value can never be negative — so i >= 0 is always
true and the loop condition can never fail. Decrementing past zero doesn't go negative
either: unsigned arithmetic is defined to wrap around modulo 2^N, so --i at 0 yields
4294967295 and the countdown restarts from the stratosphere. This is not undefined
behavior — the wraparound is guaranteed by the standard, which is exactly why the loop
so dependably never ends. The same trap hides in v.size() - 1, which on an empty
vector is 18446744073709551615, because size() returns an unsigned type.
-Wall is silent here, but -Wextra catches it:
warning: comparison of unsigned expression in '>= 0' is always true [-Wtype-limits].
The fix¶
Count down with a signed variable, or use the reverse-iteration idiom, which tests before decrementing:
for (int i = 3; i >= 0; --i) // signed: plain and correct
for (unsigned i = 4; i-- > 0;) // idiom: body sees 3, 2, 1, 0, then the loop exits
Takeaway: unsigned >= 0 is a tautology — count down with a signed type, or with
i-- > 0.
Try it: g++ -std=c++17 main.cpp -o demo && ./demo