Iterate over all unsigned integers in a for loop

Say I want to iterate over all integers in a for loop. For discussion, suppose I call some unknown function f(unsigned x) for each integer:

 for (unsigned i = 0; i < UINT_MAX; i++) { f(i); } 

Of course, the above does not iterate over all integers, since it skips one: UINT_MAX. Changing the condition to i <= UINT_MAX leads to an infinite loop, because it is a tautology.

You can do this with a do-while , but you will lose all the intricacies of the for syntax.

Can I get a cake ( for loops) and eat it (iterate over all integers)?

+10
c syntax loops for-loop
Nov 04 '16 at 23:17
source share
6 answers

You can do this with a do-while loop, but you will lose all the subtleties for the syntax.

It is still possible with a do-while loop using an anonymous block scope:

 { unsigned i = 0; do { f(i); } while (++i != 0); } 

Although this construct may not be the most idiomatic, it is an obvious candidate for a clear build code. For example, gcc -O compiles it as:

 .L2: mov edi, ebx ; ebx starts with zero call f add rbx, 1 cmp rbx, rbp ; rbp is set with 4294967296 jne .L2 
+5
Nov 04. '16 at 23:58
source share
โ€” -

You will need to run a test at the end of the loop body, like do-while:

 for (unsigned int i = 0; /* nothing */; i++) { ... if (i == UINT_MAX) { break; } } 

For the test in the standard for the position of testing the loop, you will need to track the current iteration so that you can distinguish between the states of UINT_MAX + 2: one for each entry into the body of the loop, and one for once you do not. A single unsigned int cannot handle this, so you'll need at least one helper variable or a larger loop counter.

+8
Nov 04 '16 at 23:21
source share

You can use another variable to detect when you are looping.

 for (unsigned int i = 0, repeat = 0; !(i == 0 && repeat); i++, repeat = 1) { ... } 
+3
Nov 04 '16 at 23:42 on
source share

The classic way to do your iteration efficiently with a single test is the do / while :

 unsigned i = 0; do { f(i); } while (i++ != UINT_MAX); 

If you insist on using a for loop:

 for (unsigned i = 0;; i++) { f(i); if (i == UINT_MAX) break; } 

Here is another option with two variables, where all the logic is inside the for statements:

 for (unsigned int i = 0, not_done = 1; not_done; not_done = (i++ - UINT_MAX)) { f(i); } 

It can generate slower code due to an additional variable, but, as BeeOnRope commented, clang and icc compile its very efficient code .

+2
Nov 05 '16 at
source share

An easy solution would be

 unsigned i; for (i=0; i<UINT_MAX; i++) { f(i); } f(i); // i will be UINT_MAX at this time. 
0
Nov 05 '16 at 2:32
source share

Use a large integer type:

 #include <limits.h> #include <stdio.h> int main() { for (unsigned long i = 0; i <= UINT_MAX; i++) { f(i); } } 

This version uses stdint for greater consistency.

 #include <stdio.h> #include <stdint.h> int main() { for (uint_fast64_t i = 0; i <= UINT32_MAX; ++i) { f(i); } } 
0
Nov 05 '16 at 2:47
source share



All Articles