A typical for
loop relies on being able to detect the termination condition after the last iteration of the loop. In your case, as other answers have pointed out, i <= 0xff
is always true (given that i
is of type unsigned char
and that UCHAR_MAX==0xff
, which is typical).
You can run into the same kind of problem near the bounds of any integer type. For example, this:
for (int i = INT_MAX - 9; i <= INT_MAX; i ++) {
/* ... */
}
is (probably) also an infinite loop (except that overflow for signed integer types has undefined behavior as opposed to the well-defined wraparound semantics for unsigned integers, and an optimizing compiler can take advantage of that and -- but I digress). Just don't do that.
One of many solutions is to move the test to the bottom of the loop, before the increment:
for (unsigned char i = 0; ; i ++) {
printf("%d\n", i);
if (i == 0xff) break;
}
The second clause of a for
loop is the termination condition, evaluated before each iteration. If you leave it empty, it's treated as always true, giving you an infinite loop (for (;;)
is a common idiom for a simple infinite loop). We test whether i
is equal to 0xff
at the bottom of the loop. If it is then we've just executed the last iteration, and we can break out of the loop.
(Some might prefer to use a while
loop here, but I like the for
because it lets us combine the declaration of the loop control variable and the increment in a single construct.)
(Strictly speaking the maximum value of unsigned char
isn't necessarily 0xff
or 255
, but it will be on any system you're likely to encounter. Implementations for some DSPs have CHAR_BIT > 8
, and thus UCHAR_MAX > 255
.)