Size_t 变量作为循环计数器导致分段错误。为什么循环在 i = 0 时不退出?

Size_t variable as loop counter causing segmentation fault. Why does the loop not exit once i = 0?

导致问题的代码如下所示:

for(size_t i = 10; i >= 0; i--){
   cout << i  << ", ";
}

这输出: 4, 3, 2, 1, 0, 18446744073709551615,

然后程序 returns 出现分段错误,原因很明显,它试图以荒谬的索引访问我的项目。

为什么计数器不停在0?

编辑:我正在使用网络编译器进行作业。它没有提供任何警告。通常我在本地开发然后粘贴我所做的,因为我以前遇到过编译器问题。很高兴知道即使问题很小,我也不是完全愚蠢。感谢您的帮助!只是想在给出许多答案后我会添加一些额外的信息。

size_t 是无符号整数。这意味着 i 永远不会为负。当i等于0的时候,你减去1,就会变成一个很大的数,而不是-1

条件 i >=0 基本上是说保持 运行 这个循环直到 i 小于零。由于 i 的类型,此条件永远不会满足。

您的编译器可能会向您指出这一点。我不确定您使用的是哪个编译器。但例如,如果您使用的是 gcc,则可以添加标志 -Wsign-compare-Wtype-limits.

编辑:更改为正确的 gcc 标志。致谢@Deduplicator

当您使用 for 循环从零数到九时,您执行以下操作:

for(int i = 0; i < 10; i++){
   cout << i << endl;
}

请注意,此循环的条件是 i < 10。在第 9 次迭代结束时,i 递增 (i++),然后检查 (i < 10)。

在你的情况下, i 的类型是 size_t ,它是无符号的(也不能是负数)。因为 underflow,一旦 i-- 被调用,i 从 0 变为 size_t 的最大值。由于此值为正,条件 returns 为真并且您的 for 循环继续。

如何解决这个问题?

int代替。 Size_t一般用来表示容器的大小,这里没必要写:D.

在这种情况下,size_t 是无符号的,显然它在为 0 时减 1 后达到最大值。并且可能您在代码中的某些地方使用此计数器 i 来访问一个数组元素然后越界,所以分段错误!

一个简单的解决方案如下:

for(size_t i = 10; i--;){
   std::cout << i  << ", ";
}

通过这种方式,循环将在零处停止!

如果比较总是非常正确(或错误),许多编译器会警告您。
在这种情况下,像 size_t 这样的无符号类型永远不能包含 sub-zero 值。

当然,你必须表示有兴趣得到警告,注意是可选的。

出于演示目的,请参阅 the following program compiled on coliru using gcc and clang

int main() {
    for (unsigned i = 10; i >= 0; i--)
        /**/;
}

如果您想在整个范围内工作,并继续使用单个无符号 loop-variable,重新排列一下即可完成:

for (size_t i = 11; i-->0; )
    /**/;

当然,i-->0可以简化为i--,但是我不能link"What is the "-->" operator in C++? ".