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

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

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

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

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

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

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

通过使用匿名块作用域,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 

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

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

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

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

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

通过单个测试有效实现迭代的经典方法是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编译为非常高效的代码 。

一个简单的解决方案是,

 unsigned i; for (i=0; i 

使用更大的整数类型:

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

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

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