我在Stackoverflow上对C ++中的反向循环进行了一些研究,它使用无符号整数而不是有符号整数。但我仍然不明白为什么会出现问题(见Unsigned int reverse iteration with for loops)。为什么以下代码会产生分段错误?
#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等于零时,因为有类似溢出的东西。但我认为无符号整数可以取零值,不是吗?现在,如果我用有符号整数替换它,那绝对没有问题。
有人能用无符号整数向我解释反向循环背后的机制吗?
非常感谢!
答案 0 :(得分:25)
这里的问题是无符号整数永远不会为负。
因此,循环测试:
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--)
答案 1 :(得分:6)
问题是,你的循环允许i低至零,并且只有当i小于0时才期望退出循环。因为我是无符号的,它永远不会小于0.它会翻到2 ^ 32-1。这大于矢量的大小,因此导致段错误。
答案 2 :(得分:4)
无论unsigned int i
的价值如何,i >= 0
总是如此,因此您的for
循环永远不会结束。
换句话说,如果在某个时刻i
为0且你递减它,它仍然保持非负数,因为它包含一个巨大的数字,可能是4294967295(即2 32 -1)。
答案 3 :(得分:3)
问题在于:
for (unsigned int i = 9; i >= 0; i--)
对于unsigned int,您的值为9,退出定义为i&gt; = 0,这将始终为true。 (unsigned int永远不会是负面的!!!)。因此你的循环将重新开始(无限循环,因为i = 0然后-1变为最大值)。
答案 4 :(得分:0)
正如您所说,在循环的最后一步之后发生的无符号数减少到零以下会产生溢出,该数字会环绕到其最大值,因此我们最终会陷入无限循环。
<块引用>有人可以用无符号整数向我解释反向循环背后的机制吗?
我首选的带有索引的反向循环方法是这样的:
import pandas as pd
inp = [{'a1':'Juancito 1'}, {'a1':'Juancito 2'}, {'a1':'Juancito 3'}]
df = pd.DataFrame(inp)
for i in df['a1']:
if 'Juancito' in i:
i = 'Juancito'
else:
pass
df.head()
这就是为什么,因为它最接近于等价的普通循环:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
然后如果您需要多次访问索引元素并且不想连续写入 [i - 1],则可以在循环的第一行添加类似这样的内容:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}