67

我第一次尝试执行 n 次的反向 for 循环是这样的:

for ( unsigned int i = n-1; i >= 0; i-- ) {
    ...     
}

失败了,因为在无符号算术 i中保证始终大于或等于零,因此循环条件将始终为真。幸运的是,在我不得不怀疑为什么循环无限执行之前,gcc 编译器警告我“毫无意义的比较”。


我正在寻找一种解决此问题的优雅方法,请记住:

  1. 它应该是一个向后的for循环。
  2. 循环索引应该是无符号的。
  3. n 是无符号常数。
  4. 它不应该基于无符号整数的“晦涩”环算术。

有任何想法吗?谢谢 :)

4

20 回答 20

108

怎么样:

for (unsigned i = n ; i-- > 0 ; )
{
  // do stuff with i
}
于 2009-03-20T11:35:59.477 回答
15
for ( unsigned int loopIndex = n; loopIndex > 0; --loopIndex ) {
    unsigned int i = loopIndex - 1;
    ...
} 

或者

for ( unsigned int loopIndex = 0; loopIndex < n; ++loopIndex ) {
    unsigned int i = n - loopIndex - 1;
    ...
} 
于 2009-03-20T11:30:53.297 回答
11
for ( unsigned int i = n; i != 0; i-- ) {
    // do something with i - 1
    ...     
}

请注意,如果您同时使用 C++ 和 C,当您切换到使用迭代器时,使用 != 是一个好习惯,其中 <= 等可能不可用。

于 2009-03-20T11:29:46.280 回答
11

为什么不简单:

unsigned int i = n;
while(i--)
{ 
    // use i
}

这符合问题正文中列举的所有要求。它不使用任何可能导致代码审查失败或违反编码标准的东西。我能看到的唯一反对意见是,如果 OP 真的坚持for循环而不是生成 i = (n-1) .. 0 的直接方式。

于 2011-05-11T07:30:40.407 回答
9

我倾向于使用

 for ( unsigned int i = n; i > 0; )  {
    --i;
    ...     
 }

它与skizz的答案几乎相同,(它错过了最终不必要的递减,但编译器应该优化掉它),实际上会通过代码审查。我必须使用的每个编码标准在条件规则中都没有变化。

于 2009-03-20T11:44:44.650 回答
8
for ( unsigned int i = n; i > 0; i-- ) {
    ...  
    i-1 //wherever you've been using i   
}
于 2009-03-20T11:30:10.210 回答
5

也许这样?恕我直言,它清晰易读。如果以某种方式隐含地知道 if(n>=1),则可以省略它。

if(n>=1) {
    // Start the loop at last index
    unsigned int i = n-1;
    do {
       // a plus: you can use i, not i-1 here
    } while( i-- != 0 );
}

另一个版本:

if(n>=1) {
    unsigned int i = n;
    do {
       i--;

    } while( i != 0 );
}

第一个没有 if 语句的代码如下所示:

unsigned int i = n-1;
do {

} while( i-- != 0 );
于 2009-03-20T11:52:18.143 回答
4
for (unsigned int i = n-1; i<(unsigned int)-1; i--)

好的,它的“晦涩的环算术”。

于 2009-03-20T12:34:38.027 回答
4

unsigned int或者,如果您需要从 n-1 到 0 的索引,您可以依赖包装行为

for(unsigned int i = n-1; i < n; i--) {
    ...
}
于 2009-03-20T13:05:42.133 回答
3
for ( unsigned int i = n; i > 0; i-- ) {
    unsigned int x = i - 1;
    // do whatever you want with x    
}

当然不优雅,但它的工作原理。

于 2009-03-20T11:32:00.547 回答
3

我提到这个选项的唯一原因是因为我没有在列表中看到它。

for ( unsigned int i = n-1; i < n; i-- ) {
... 
}

完全违背直觉,但它确实有效。它起作用的原因是因为从 0 中减去 1 会产生可以用无符号整数表示的最大数字。

一般来说,我不认为使用无符号整数和算术是一个好主意,尤其是在减法时。

于 2009-03-20T13:08:40.643 回答
2

很简单,只需在 -1 处停止:

for( unsigned int i = n; i != -1; --i )
{
 /* do stuff with i */
}

编辑:不知道为什么这会被否决。它有效,并且比上述任何一种都更简单、更明显。

于 2009-09-06T21:56:26.763 回答
1
for ( unsigned int i = n; i > 0; i-- ) {
    ...     
}

应该可以正常工作。如果您需要将i变量用作数组的索引,请执行以下操作:

array[i-1];
于 2009-03-20T11:31:16.120 回答
1

嗯。以下是您的选择:

  1. i=0用作您的中断条件 - 当 i 达到 0 时循环不会执行,因此在循环退出后执行循环内容的 1 次迭代i=0
for ( unsigned int i = n-1; i > 0; i-- ) {
    doStuff(i);
}
doStuff(0);
  1. 在循环中,测试i=0break输出。不推荐,因为现在您要在循环中两次测试 i 的值。在循环中使用 break 通常也被视为不好的做法。
for ( unsigned int i = n-1; i >= 0; i-- ) {
    doStuff(i);
    if (i=0) break;
}
于 2009-03-20T11:39:29.983 回答
1
unsigned index;
for (unsigned i=0; i<n; i++)
{
    index = n-1 - i; // {i == 0..n-1} => {index == n-1..0}
}
于 2009-03-20T14:20:55.977 回答
0

由于这不是循环的标准,我可能会使用 while 循环,例如:

unsigned int i = n - 1;
while (1)
{
    /* do stuff  with i */

     if (i == 0)
    {
        break;
    }
    i--;
}
于 2009-03-20T12:25:17.517 回答
0

这是未经测试的,但您可以执行以下操作:

for (unsigned int i, j = 0; j < n; i = (n - ++j)) {
    /* do stuff with i */
}
于 2009-03-20T12:32:42.710 回答
0

使用两个变量,一个用于向上计数,另一个用于数组索引:

unsigned int Index = MAX - 1;
unsigned int Counter;
for(Counter = 0; Counter < MAX; Counter++)
{
    // Use Index
    Index--;
}
于 2009-03-21T17:15:16.643 回答
-1
for ( unsigned int i = n-1; (n-i) >= 0; i-- ) {
    // n-i will be negative when the loop should stop.
    ...     
}
于 2009-03-20T11:32:49.827 回答
-6

埃兹:

#define unsigned signed

for ( unsigned int i = n-1; i >= 0; i-- ) { ... 
}
于 2009-09-06T22:20:41.120 回答