2012-01-28 15 views
8

我对C++中使用无符号整数而不是有符号整数的循环进行了反转的Stackoverflow做了一些研究。但我仍然不明白为什么会出现问题(请参阅Unsigned int reverse iteration with for loops)。为什么下面的代码会产生分段错误?C++ for循环中的无符号整数

#include <vector> 
#include <iostream> 
using namespace std; 

int main(void) 
{ 
    vector<double> x(10); 

    for (unsigned int i = 9; i >= 0; i--) 
    { 
     cout << "i= " << i << endl; 
     x[i] = 1.0; 
    } 

    cout << "x0= " << x[0] << endl; 

    return 0; 
} 

我知道问题是当索引i等于零,因为有像溢出一样的东西。但我认为一个无符号整数可以取零值,不是吗?现在,如果我用有符号整数替换它,那绝对没有问题。

有人可以解释我背后的反向循环与无符号整数的机制?

非常感谢!

+3

对于无符号'i','i> = 0'总是如此,所以循环永远不会终止。 – TonyK 2012-01-28 08:58:35

+0

阅读编译器警告,它们很有用。在这种情况下,您的编译器应该已经警告过您,循环中的条件始终为真。 – dragonroot 2012-01-28 09:20:05

+0

@dragonroot:不幸的不是。我使用g ++的-Wall标志。你知道一个编译器标志可以检测到这种问题吗?谢谢。 – Benjamin 2012-01-28 09:27:44

回答

24

这里的问题是一个无符号整数永远不会是负数。

因此,循环测试:

i >= 0 

永远是正确的。因此你得到一个无限循环。

当它下降到零以下时,它将包装到最大值unsigned值。
因此,你也将访问x[i]出界外

这不是一个有符号整数,因为它会简单地去否定,因而不能i >= 0问题。

因此,如果你想使用无符号整数,你可以尝试以下可能性之一:

for (unsigned int i = 9; i-- != 0;) 

for (unsigned int i = 9; i != -1; i--) 

这两个被GManNickG和AndreyT从意见建议。


下面是我原来的3个版本:

for (unsigned int i = 9; i != (unsigned)0 - 1; i--) 

for (unsigned int i = 9; i != ~(unsigned)0; i--) 

for (unsigned int i = 9; i != UINT_MAX; i--) 
+0

或者'i'​​比索引*多一个*,因此'0'是一个正确的终止条件。像其他人一样棘手。 – 2012-01-28 13:23:31

+0

不是整数溢出和下溢未定义的行为? – josefx 2012-01-28 14:17:44

+2

@josefx只有有符号整数溢出/下溢是未定义的行为。 – Mysticial 2012-01-28 18:19:44

4

不管的unsigned int i值它始终是真实的i >= 0桑尼我们的for循环永不结束。

换句话说,如果在某个时刻i是0,你递减它,它仍然保持非负,因为它则蕴含着巨大的数字,大概4294967295(即2 -1)。

6

问题是,你的循环允许i到低至为零,仅期望退出循环如果i小于0。由于i是无符号的,它可以永远不会小于0。翻转到2^32-1。这大于你的矢量的大小,因此导致段错误。

3

的问题是在这里:

for (unsigned int i = 9; i >= 0; i--) 

你开始与一个unsigned int a的9价值和你退出定义为i> = 0,这将是总是如此。 (unsigned int永远不会是负面的!!!)。正因为如此,你的循环将重新开始(无限循环,因为我= 0,然后-1变成最大值)。