对于使用无符号整数时循环条件停止在0?

我有一个必须从N到0(包括)的循环。 我的i变量的类型为size_t ,通常是无符号的。 我目前正在使用以下代码:

 for (size_t i = N; i != (size_t) -1; --i) { ... } 

那是对的吗? 有没有更好的方法来处理这种情况?

谢谢,

文森特。

是的,这是正确的,这是一种非常常见的方法。 我不会考虑改变它。

无符号整数类型的算法保证使用模2^N算术(其中N是类型中的值位数),并且很好地定义了溢出时的行为。 通过加上或减去2^N倍数(即模2^N算术)将结果转换为02^N - 1的范围。

-1转换为无符号整数类型( size_t为1)转换为2^N - 1--对无符号类型也使用模2^N算术,因此值为0的无符号类型将递减为2^N - 1 。 您的循环终止条件是正确的。

只是因为在每次迭代开始时有一个方便的地方进行测试并不意味着你必须使用它。 要处理N到0( 包括 N),测试应该在最后,至少如果您关心处理最大值。 不要让方便你把测试放在错误的地方。

 for (size_t i = N;; --i) { ... if (i == 0) break; } 

一个do-while循环也可以工作,但是你还要放弃i作为循环的范围。

你可以用这个:

 for (size_t i = n + 1; i-- > 0;) { } 

希望有所帮助。

就个人而言,我只会使用不同的循环结构,但每个都使用自己的:

 size_t i = N; do { ... } while (i --> 0); 

(你可以使用(i--)作为循环条件,但是人们永远不应该(i--)使用--> “operator”的机会。

 for ( size_t i = N ; i <= N ; i-- ) { .... } 

这样做是因为size_t是unsigned int。 无符号整数是32位。 当变量i的值为0时,您希望循环执行条件。 如果你执行i--,计算机就可以

  00000000000000000000000000000000 -00000000000000000000000000000001 

这导致明显溢出,给出值111111111 ... 1。 对于带符号的二进制补码整数,该值显然为负。 但是,i的类型是unsigned int,因此计算机将111111 ... 1解释为非常大的正值。

所以你有几个选择:

1)如上所述,并在发生溢出时使循环终止。

2)使循环从i = 0运行到i <= N,但在循环中的任何地方使用(Ni)代替i。 例如,myArray [i]将成为myArray [Ni](取决于N的实际值代表的值)。

3)使你的for循环的条件利用一元运算符的优先级。 正如另一位用户发布的

 for ( size_t i = N + 1 ; i-- > 0 ; ) { ... } 

这将i设置为N + 1,检查条件N + 1> 0是否仍然成立。 确实如此,但是i--有副作用,因此i的值减少到i = N.继续进行直到你得到i = 1.条件将被测试,1> 0为真,副作用发生,然后我= 0并执行。

您可以使用第二个变量作为循环计数器,以使未来的审阅者清楚地了解迭代范围。

 for (size_t j=0, i=N; j<=N; ++j, --i) { // code here ignores j and uses i which runs from N to 0 ... } 
 for (i=N; i+1; i--) 

由于无符号整数在从零递减时将滚动到其最大值,因此如果N小于该最大值,则可以尝试以下操作(如果这是UB,有人请纠正我):

 for ( size_t i = N; i <= N; i-- ) { /* ... */ }