In article <xG*******************@newsb.telia.net>
eiaks <ja**@hotmail.com> wrote:
Both this:
unsigned char c;
for (c = 0; c < 256; c++)
and
for (c = 0; c <= 255; c++)
will result in an infinite loop since c can't be larger than 255.
Indeed: if UCHAR_MAX is 255, then when c==255, c++ has the same
effect as "c = 0" (because 255+1 is congruent to zero mod 256, as
the mathematicians say it).
As others noted, this particular case can be solved by counting in
"int" (which goes to at least +32767, and often higher). But there
are some situations in which C's "for" loop simply does not do the
desired job. For instance, suppose that, in C89 (not C99 hence
no "long long" type), you wish to iterate over every possible
"unsigned long" value. An attempt like:
unsigned long ul;
for (ul = 0; ul <= ULONG_MAX; ul++)
is an infinite loop, just as with the example above with unsigned
char. What is needed is a loop construct with a test-at-bottom.
C has one, but it is clumsier than a "for" loop. Just as most
people prefer a "for" loop for iterating through a list:
for (p = head; p != NULL; p = p->next)
or looping zero-or-more times through a case that does not hit
integer boundary problems:
for (i = 0; i < n; i++)
we might "prefer" a "for_until_with_test_at_bottom" loop in which
we could write:
for_until_test_at_bottom (ul = 0; ul != ULONG_MAX; ul++) {
... code ...
}
Instead, in C, we have to write, e.g.:
ul = 0;
do {
... code ...
continue_here: ;
} while (ul++ != ULONG_MAX);
and replace any "continue" statements in the "code" section with
"goto continue_label". (If there are no such statements, we can
omit the label and the empty statement that goes with it.) This
construct *also* depends on the fact that "ul++" is well defined
even if ul was ULONG_MAX (here ul becomes 0). (We could write this
as "do { ... } while (++ul != 0);" as well.) If the termination
condition might overflow -- as is true with signed integers -- we
have at least a technical problem, as the "++" might trap (even
though Real C Compilers never do, even on machines on which they
could -- it is usually more important to produce wrong answers fast
than to catch the error, after all :-) ).
Fortunately there is a third alternative. Although some purists
object to it, it neatly implements *all* forms of loops, including
test-at-top, test-at-bottom, and the occasional test-in-the-middle
"loop-and-a-half" that comes up now and then:
for (ul = 0;; ul++) {
... some code here ...
if (should_terminate_loop)
break;
... more code here ...
}
where either "code" section can be eliminated. (Of course, if the
first section is eliminated, we can just move the termination
condition into the "for" statement, and invert the sense.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it
http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.