使用无符号索引进行反向'for'循环的最佳方法是什么?

时间:2009-03-20 11:26:09

标签: c for-loop

我第一次尝试反向循环这样做了n次:

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

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


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

  1. 它应该是一个向后循环。
  2. 循环索引应该是无符号的。
  3. n是无符号常量。
  4. 它不应该基于无名整数的“模糊”环算法。
  5. 有什么想法吗?谢谢:))

20 个答案:

答案 0 :(得分:94)

怎么样:

for (unsigned i = n ; i-- > 0 ; )
{
  // do stuff with i
}

答案 1 :(得分:12)

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;
    ...
} 

答案 2 :(得分:11)

for ( unsigned int i = n; i != 0; i-- ) {
    // do something with i - 1
    ...     
}

请注意,如果您使用C ++以及C,那么在切换到使用迭代器时,使用!=是一个很好的习惯,其中&lt; =等可能不可用。

答案 3 :(得分:9)

为什么不简单:

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

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

答案 4 :(得分:8)

for ( unsigned int i = n; i > 0; i-- ) {
    ...  
    i-1 //wherever you've been using i   
}

答案 5 :(得分:8)

我倾向于使用

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

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

答案 6 :(得分: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 );

答案 7 :(得分:4)

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

好吧,它的“模糊环算术”。

答案 8 :(得分:4)

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

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

答案 9 :(得分:3)

for ( unsigned int i = n; i > 0; i-- ) {
    unsigned int x = i - 1;
    // do whatever you want with x    
}

当然不优雅,但它有效。

答案 10 :(得分:3)

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

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

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

一般来说,我认为使用无符号整数和关节运算并不是一个好主意,特别是在减去时。

答案 11 :(得分:2)

很简单,只需停在-1:

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

编辑:不确定为什么这会被贬低。它起作用,它比上述任何一个更简单,更明显。

答案 12 :(得分:1)

嗯。您可以选择以下选项:

  1. 使用i=0作为中断条件 - 当i到达0时循环不会执行,因此在循环退出后执行i=0的循环内容的1次迭代。
  2. for ( unsigned int i = n-1; i > 0; i-- ) {
        doStuff(i);
    }
    doStuff(0);
    
    1. 在循环中,测试i=0break。不推荐,因为现在你在循环中测试了两次i的值。在循环中使用break通常也是不好的做法。
    2. for ( unsigned int i = n-1; i >= 0; i-- ) {
          doStuff(i);
          if (i=0) break;
      }
      

答案 13 :(得分:1)

unsigned index;
for (unsigned i=0; i<n; i++)
{
    index = n-1 - i; // {i == 0..n-1} => {index == n-1..0}
}

答案 14 :(得分:1)

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

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

array[i-1];

答案 15 :(得分:0)

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

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

     if (i == 0)
    {
        break;
    }
    i--;
}

答案 16 :(得分:0)

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

for (unsigned int i, j = 0; j < n; i = (n - ++j)) {
    /* do stuff with i */
}

答案 17 :(得分:0)

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

unsigned int Index = MAX - 1;
unsigned int Counter;
for(Counter = 0; Counter < MAX; Counter++)
{
    // Use Index
    Index--;
}

答案 18 :(得分:-1)

for ( unsigned int i = n-1; (n-i) >= 0; i-- ) {
    // n-i will be negative when the loop should stop.
    ...     
}

答案 19 :(得分:-3)

e.z:

#define unsigned signed

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