导致问题的代码如下所示:
for(size_t i = 10; i >= 0; i--){
cout << i << ", ";
}
该输出:4,3,2,1,0,18446744073709551615,
然后程序返回一个分段错误,原因很明显,它试图访问荒谬索引中的项目。
为什么计数器不在0停止?
编辑:我在用网络编译器做作业。它没有提供任何警告。一般来说,我在本地开发,然后粘贴我所做的内容,因为我以前遇到过编译器问题。很高兴知道我并没有完全愚蠢,尽管问题很小。谢谢你的帮助!只是想我会在给出许多答案后添加一些额外的信息。
size_t
是一个无符号积分。这意味着i
永远不可能是负的。当i
等于0
,减去1
,它将变成一个很大的数字,而不是-1
。
条件i >=0
基本上说继续运行这个循环,直到i
小于零。由于i
的类型,这个条件永远不会满足。
编译器可能会向您指出这一点。我不确定你在用哪个编译器。但例如,如果使用gcc,则可以添加标志-Wsign-compare
-Wtype-limits
。
编辑:更改为正确的gcc标志。积分转到@重复数据消除
当使用for循环从零到九进行计数时,需要执行以下操作:
for(int i = 0; i < 10; i++){
cout << i << endl;
}
注意,该循环的条件是i<10.在第九次迭代结束时,i被递增(i++
(,然后被检查(i < 10
(。
在您的情况下,i的类型是size_t
,它是无符号的(也就是说,不能为负数(。由于下溢,一旦调用i--
,i将从0变为size_t
的最大值。由于该值为正,条件将返回true,for循环将继续。
如何解决此问题
请改用int
Size_t通常用于表示容器的大小,这里不需要有:D。
如果比较总是非常正确(或错误(,许多编译器都会发出警告
在这种情况下,像size_t
这样的无符号类型永远不能包含零以下的值。
当然,你必须表示有兴趣得到警告,注意是可选的。
为了便于演示,请参阅以下使用gcc和clang 在coliru上编译的程序
int main() {
for (unsigned i = 10; i >= 0; i--)
/**/;
}
如果你想处理整个范围,并使用单个无符号循环变量,重新排列一点就可以完成:
for (size_t i = 11; i-->0; )
/**/;
当然,i-->0
可以简化为i--
,但我无法链接">什么是"-->quot;C++中的运算符";。
在这种情况下,size_t是无符号的,很明显,当它为0时,它会在减少1后达到最大值。可能你在代码中的某个地方使用了这个计数器i
来访问数组元素,然后它超出了边界,所以分段错误!
一个简单的解决方案看起来像:
for(size_t i = 10; i--;){
std::cout << i << ", ";
}
通过这种方式,循环将挑衅地停止在零!