Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over all unsigned integers in a for loop

Let's say I want to iterate over all integers in a for loop. For the sake of discussion, assume I am calling some unknown function f(unsigned x) for each integer:

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

Of course, the above fails to iterate over all integers, because it misses one: UINT_MAX. Changing the condition to i <= UINT_MAX just results in an infinite loop, because that's a tautology.

You can do it with a do-while loop, but you lose all the niceties of the for syntax.

Can I have my cake (for loops) and eat it too (iterate over all integers)?

like image 273
BeeOnRope Avatar asked Nov 04 '16 23:11

BeeOnRope


2 Answers

You'll have to perform the test at the end of the loop body, much like a do-while:

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

For a test in the standard for loop test position to work, you would need to track the current iteration in a way that can distinguish between UINT_MAX+2 states: one for each time you enter the loop body, and one for the one time you don't. A single unsigned int can't handle that, so you'd need at least one auxiliary variable or a bigger loop counter.

like image 154
user2357112 supports Monica Avatar answered Sep 22 '22 17:09

user2357112 supports Monica


You can do it with a do-while loop, but you lose all the niceties of the for syntax.

It is still doable with do-while loop by using an anonymous block scope:

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

While this construct may not be most idiomatic, it is an obvious candidate for clear assembly 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
like image 43
Grzegorz Szpetkowski Avatar answered Sep 21 '22 17:09

Grzegorz Szpetkowski