My first attempt of reverse for loop that does something n times was something like:
我第一次尝试反向循环,做了n次这样的事情:
for ( unsigned int i = n-1; i >= 0; i-- ) {
...
}
This fails because in unsigned arithmetic i
is guaranteed to be always greater or equal than zero, hence the loop condition will always be true. Fortunately, gcc compiler warned me about a 'pointless comparison' before I had to wonder why the loop was executing infinitely.
这之所以失败,是因为在无符号算术中,i总是大于或等于零,因此循环条件总是为真。幸运的是,gcc编译器在我不得不考虑循环为什么无限执行之前就警告我一个“无意义的比较”。
I'm looking for an elegant way of resolving this issue keeping in mind that:
我在寻找一种优雅的方式来解决这个问题,记住:
- It should be a backwards for loop.
- 它应该是一个反向循环。
- The loop index should be unsigned.
- 循环索引应该是无符号的。
- n is unsigned constant.
- n是无符号常数。
- It should not be based on the 'obscure' ring arithmetics of unsigned integers.
- 它不应该基于无符号整数的“模糊”环算术。
Any ideas? Thanks :)
什么好主意吗?谢谢:)
20 个解决方案
#1
83
How about:
如何:
for (unsigned i = n ; i-- > 0 ; )
{
// do stuff with i
}
#2
11
for ( unsigned int loopIndex = n; loopIndex > 0; --loopIndex ) {
unsigned int i = loopIndex - 1;
...
}
or
或
for ( unsigned int loopIndex = 0; loopIndex < n; ++loopIndex ) {
unsigned int i = n - loopIndex - 1;
...
}
#3
11
for ( unsigned int i = n; i != 0; i-- ) {
// do something with i - 1
...
}
Note that if you use C++ as well as C, using != is a good habit to get into for when you switch to using iterators, where <= etc. may not be available.
注意,如果您使用c++和C,那么当您切换到使用迭代器时,使用!=是一个很好的习惯,其中<=等可能不可用。
#4
8
for ( unsigned int i = n; i > 0; i-- ) {
...
i-1 //wherever you've been using i
}
#5
8
I'd tend to use
我倾向于使用
for ( unsigned int i = n; i > 0; ) {
--i;
...
}
it's almost the same as skizz' answer, (it misses out a final unnecessary decrement, but the compiler should optimise that away), and actually will pass code review. Every coding standard I've had to work with has had a no-mutation in conditional rule.
它几乎和skizz的答案一样,(它遗漏了最后一个不必要的减量,但是编译器应该优化它),并且实际上会通过代码审查。我使用过的每一个编码标准都有条件规则的无突变。
#6
8
Why not simply:
为什么不简单:
unsigned int i = n;
while(i--)
{
// use i
}
This meets all the requirement enumerated in the body of the question. It doesn't use anything likely to fail code review or violate a coding standard. The only objection I could see to it is if the OP really insisted on a for
loop and not a straightforward way of generating i = (n-1) .. 0.
这满足了问题主体中列出的所有需求。它不使用任何可能失败代码检查或违反代码标准的东西。我能看到的唯一反对意见是,如果OP真的坚持一个for循环,而不是直接生成I = (n-1)的方法。0。
#7
5
Maybe this way? IMHO its clear and readable. You can omit the if(n>=1) if it is implicitly known somehow.
也许这种方式?它清晰易读。如果隐式知道的话,可以省略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 );
}
Another version:
另一个版本:
if(n>=1) {
unsigned int i = n;
do {
i--;
} while( i != 0 );
}
The first code without if statement would look like:
第一个没有if语句的代码如下:
unsigned int i = n-1;
do {
} while( i-- != 0 );
#8
4
Or you could rely on the wrapping behaviour of unsigned int
if you need indexing from n-1 to 0
或者,如果需要从n-1到0进行索引,则可以依赖无符号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
}
Certainly not elegant, but it works.
当然不是很优雅,但是很有效。
#10
3
for (unsigned int i = n-1; i<(unsigned int)-1; i--)
OK, its "obscure ring arithmetic".
它的“模糊环算法”。
#11
3
The only reason I mention this option is because I did not see it in the list.
我提到这个选项的唯一原因是我没有在列表中看到它。
for ( unsigned int i = n-1; i < n; i-- ) {
...
}
Totally against intuition, but it works. the reason it works is because subtracting 1 from 0 yields the largest number that can be represented by an unsigned integer.
完全与直觉相反,但它确实有效。它起作用的原因是,从0中减去1可以得到一个无符号整数表示的最大数字。
In general I do not think it is a good idea to work with unsigned integers and arthmetic, especially when subtracting.
一般来说,我不认为使用无符号整数和拟合整数是一个好主意,尤其是减法。
#12
2
Easy, just stop at -1:
很简单,只要停在-1:
for( unsigned int i = n; i != -1; --i )
{
/* do stuff with i */
}
edit: not sure why this is getting downvoted. it works and it's simpler and more obvious than any of the above.
编辑:不知道为什么会被否决。它很有效,而且比上面的任何一个都简单和明显。
#13
1
for ( unsigned int i = n; i > 0; i-- ) {
...
}
Should work fine. If you need to use the i
variable as an index into an array do it like this:
可正常工作。如果你需要使用i变量作为索引,你可以这样做:
array[i-1];
#14
1
Hm. Here are your options:
嗯。这是你的选择:
- Use
i=0
as your break condition - Loop will not execute when i reaches 0, so execute 1 iteration of the loop contents fori=0
after the loop has exited. - 使用i=0作为断点条件——当i达到0时,循环将不会执行,因此在循环退出后,对i=0执行循环内容的1次迭代。
for ( unsigned int i = n-1; i > 0; i-- ) {
doStuff(i);
}
doStuff(0);
- In the loop, test for
i=0
andbreak
out. Not recommended because now you're testing the value of i twice in the loop. Also using break within a loop is generally regarding as bad practice. - 在循环中,测试i=0并断开。不推荐,因为现在您在循环中测试了我两次的值。在循环中使用break通常是指错误的实践。
for ( unsigned int i = n-1; i >= 0; i-- ) {
doStuff(i);
if (i=0) break;
}
#15
1
unsigned index;
for (unsigned i=0; i<n; i++)
{
index = n-1 - i; // {i == 0..n-1} => {index == n-1..0}
}
#16
0
This is untested, but could you do the following:
这是未经测试的,但你能做以下事情吗?
for (unsigned int i, j = 0; j < n; i = (n - ++j)) {
/* do stuff with i */
}
#17
0
Use two variables, one to count up, and the other for the array index:
使用两个变量,一个用于计数,另一个用于数组索引:
unsigned int Index = MAX - 1;
unsigned int Counter;
for(Counter = 0; Counter < MAX; Counter++)
{
// Use Index
Index--;
}
#18
0
Since this is not a standard for loop I would probably use a while loop instead, e.g.:
由于这不是循环的标准,我可能会使用while循环,例如:
unsigned int i = n - 1;
while (1)
{
/* do stuff with i */
if (i == 0)
{
break;
}
i--;
}
#19
-1
for ( unsigned int i = n-1; (n-i) >= 0; i-- ) {
// n-i will be negative when the loop should stop.
...
}
#20
-1
e.z:
e.z:
#define unsigned signed
for ( unsigned int i = n-1; i >= 0; i-- ) { ...
}
#1
83
How about:
如何:
for (unsigned i = n ; i-- > 0 ; )
{
// do stuff with i
}
#2
11
for ( unsigned int loopIndex = n; loopIndex > 0; --loopIndex ) {
unsigned int i = loopIndex - 1;
...
}
or
或
for ( unsigned int loopIndex = 0; loopIndex < n; ++loopIndex ) {
unsigned int i = n - loopIndex - 1;
...
}
#3
11
for ( unsigned int i = n; i != 0; i-- ) {
// do something with i - 1
...
}
Note that if you use C++ as well as C, using != is a good habit to get into for when you switch to using iterators, where <= etc. may not be available.
注意,如果您使用c++和C,那么当您切换到使用迭代器时,使用!=是一个很好的习惯,其中<=等可能不可用。
#4
8
for ( unsigned int i = n; i > 0; i-- ) {
...
i-1 //wherever you've been using i
}
#5
8
I'd tend to use
我倾向于使用
for ( unsigned int i = n; i > 0; ) {
--i;
...
}
it's almost the same as skizz' answer, (it misses out a final unnecessary decrement, but the compiler should optimise that away), and actually will pass code review. Every coding standard I've had to work with has had a no-mutation in conditional rule.
它几乎和skizz的答案一样,(它遗漏了最后一个不必要的减量,但是编译器应该优化它),并且实际上会通过代码审查。我使用过的每一个编码标准都有条件规则的无突变。
#6
8
Why not simply:
为什么不简单:
unsigned int i = n;
while(i--)
{
// use i
}
This meets all the requirement enumerated in the body of the question. It doesn't use anything likely to fail code review or violate a coding standard. The only objection I could see to it is if the OP really insisted on a for
loop and not a straightforward way of generating i = (n-1) .. 0.
这满足了问题主体中列出的所有需求。它不使用任何可能失败代码检查或违反代码标准的东西。我能看到的唯一反对意见是,如果OP真的坚持一个for循环,而不是直接生成I = (n-1)的方法。0。
#7
5
Maybe this way? IMHO its clear and readable. You can omit the if(n>=1) if it is implicitly known somehow.
也许这种方式?它清晰易读。如果隐式知道的话,可以省略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 );
}
Another version:
另一个版本:
if(n>=1) {
unsigned int i = n;
do {
i--;
} while( i != 0 );
}
The first code without if statement would look like:
第一个没有if语句的代码如下:
unsigned int i = n-1;
do {
} while( i-- != 0 );
#8
4
Or you could rely on the wrapping behaviour of unsigned int
if you need indexing from n-1 to 0
或者,如果需要从n-1到0进行索引,则可以依赖无符号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
}
Certainly not elegant, but it works.
当然不是很优雅,但是很有效。
#10
3
for (unsigned int i = n-1; i<(unsigned int)-1; i--)
OK, its "obscure ring arithmetic".
它的“模糊环算法”。
#11
3
The only reason I mention this option is because I did not see it in the list.
我提到这个选项的唯一原因是我没有在列表中看到它。
for ( unsigned int i = n-1; i < n; i-- ) {
...
}
Totally against intuition, but it works. the reason it works is because subtracting 1 from 0 yields the largest number that can be represented by an unsigned integer.
完全与直觉相反,但它确实有效。它起作用的原因是,从0中减去1可以得到一个无符号整数表示的最大数字。
In general I do not think it is a good idea to work with unsigned integers and arthmetic, especially when subtracting.
一般来说,我不认为使用无符号整数和拟合整数是一个好主意,尤其是减法。
#12
2
Easy, just stop at -1:
很简单,只要停在-1:
for( unsigned int i = n; i != -1; --i )
{
/* do stuff with i */
}
edit: not sure why this is getting downvoted. it works and it's simpler and more obvious than any of the above.
编辑:不知道为什么会被否决。它很有效,而且比上面的任何一个都简单和明显。
#13
1
for ( unsigned int i = n; i > 0; i-- ) {
...
}
Should work fine. If you need to use the i
variable as an index into an array do it like this:
可正常工作。如果你需要使用i变量作为索引,你可以这样做:
array[i-1];
#14
1
Hm. Here are your options:
嗯。这是你的选择:
- Use
i=0
as your break condition - Loop will not execute when i reaches 0, so execute 1 iteration of the loop contents fori=0
after the loop has exited. - 使用i=0作为断点条件——当i达到0时,循环将不会执行,因此在循环退出后,对i=0执行循环内容的1次迭代。
for ( unsigned int i = n-1; i > 0; i-- ) {
doStuff(i);
}
doStuff(0);
- In the loop, test for
i=0
andbreak
out. Not recommended because now you're testing the value of i twice in the loop. Also using break within a loop is generally regarding as bad practice. - 在循环中,测试i=0并断开。不推荐,因为现在您在循环中测试了我两次的值。在循环中使用break通常是指错误的实践。
for ( unsigned int i = n-1; i >= 0; i-- ) {
doStuff(i);
if (i=0) break;
}
#15
1
unsigned index;
for (unsigned i=0; i<n; i++)
{
index = n-1 - i; // {i == 0..n-1} => {index == n-1..0}
}
#16
0
This is untested, but could you do the following:
这是未经测试的,但你能做以下事情吗?
for (unsigned int i, j = 0; j < n; i = (n - ++j)) {
/* do stuff with i */
}
#17
0
Use two variables, one to count up, and the other for the array index:
使用两个变量,一个用于计数,另一个用于数组索引:
unsigned int Index = MAX - 1;
unsigned int Counter;
for(Counter = 0; Counter < MAX; Counter++)
{
// Use Index
Index--;
}
#18
0
Since this is not a standard for loop I would probably use a while loop instead, e.g.:
由于这不是循环的标准,我可能会使用while循环,例如:
unsigned int i = n - 1;
while (1)
{
/* do stuff with i */
if (i == 0)
{
break;
}
i--;
}
#19
-1
for ( unsigned int i = n-1; (n-i) >= 0; i-- ) {
// n-i will be negative when the loop should stop.
...
}
#20
-1
e.z:
e.z:
#define unsigned signed
for ( unsigned int i = n-1; i >= 0; i-- ) { ...
}