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

时间:2016-11-04 23:17:17

标签: c loops for-loop syntax

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

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

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

您可以使用do-while循环执行此操作,但会丢失for语法的所有细节。

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

6 个答案:

答案 0 :(得分:8)

你必须在循环体的末尾执行测试,就像做一次:

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

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

答案 1 :(得分:5)

  

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

使用匿名块作用域仍可以使用do-while循环:

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

虽然这种结构可能不是最惯用的,但它显然是清晰汇编代码的候选者。例如,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

答案 2 :(得分:3)

你可以使用另一个变量来检测你何时循环。

for (unsigned int i = 0, repeat = 0; !(i == 0 && repeat); i++, repeat = 1) {
    ...
}

答案 3 :(得分:2)

通过单个测试有效实现迭代的经典方法是do / while循环:

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

如果您坚持使用for循环:

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

这是另一个带有2个变量的变体,其中所有逻辑都在for表达式中:

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

由于额外的变量,它可能会产生较慢的代码,但正如BeeOnRope评论的那样,clangicc将其编译为very efficient code

答案 4 :(得分:0)

一个简单的解决方案就是,

unsigned i;
for (i=0; i<UINT_MAX; i++) {
  f(i);
}
f(i);  // i will be UINT_MAX at this time.

答案 5 :(得分:0)

使用更大的整数类型:

#include <limits.h>
#include <stdio.h>

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

此版本使用stdint来提高一致性

#include <stdio.h>
#include <stdint.h>

int main() {
    for (uint_fast64_t i = 0; i <= UINT32_MAX; ++i) {
        f(i);
    }
}