Skip to content

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

Open in Compiler Explorer ↗ Quiz this entry