迭代for循环中的所有无符号整数

Bee*_*ope 10 c syntax loops for-loop

假设我想在循环中迭代所有整数for.为了便于讨论,假设我f(unsigned x)为每个整数调用一些未知函数:

for (unsigned i = 0; i < UINT_MAX; i++) {
     f(i);
}
Run Code Online (Sandbox Code Playgroud)

当然,上面的代码无法遍历所有整数,因为它错过了一个:UINT_MAX.将条件更改为i <= UINT_MAX仅导致无限循环,因为这是一个重言式.

你可以用do-while循环来完成它,但是你会失去for语法的所有细节.

我可以吃蛋糕(for循环)并吃掉它(迭代所有整数)吗?

use*_*ica 8

你必须在循环体的末尾执行测试,就像一个do-while:

for (unsigned int i = 0; /* nothing */; i++) {
    ...
    if (i == UINT_MAX) {
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

要使循环测试位置标准中的测试起作用,您需要以能够区分UINT_MAX + 2状态的方式跟踪当前迭代:每次进入循环体时一个,一次一次别.单个unsigned int无法处理,因此您至少需要一个辅助变量或更大的循环计数器.

  • 是的blarg,比某些方面的"do-while"更加混乱,但至少是对循环体的范围. (2认同)

Grz*_*ski 5

你可以使用do-while循环来完成它,但是你会失去for语法的所有细节.

通过使用匿名块作用域,do-while循环仍然可行:

{
    unsigned i = 0;
    do { f(i); } while (++i != 0);
}
Run Code Online (Sandbox Code Playgroud)

虽然这种结构可能不是最惯用的,但它显然是清晰汇编代码的候选者.例如,gcc -O将其编译为:

.L2:
        mov     edi, ebx   ; ebx starts with zero
        call    f
        add     rbx, 1
        cmp     rbx, rbp   ; rbp is set with 4294967296
        jne     .L2
Run Code Online (Sandbox Code Playgroud)

  • 是的,关于汇编它编译得很好,与其他最好编译的解决方案一致,这些解决方案似乎使用64位寄存器来进行计数.与`clang`相比,`gcc`在整体上看起来特别差.最简单的循环只是[什么`clang`做](https://godbolt.org/g/twevkT),它实际上可以减少至少一个周期. (2认同)