为什么在上一次迭代中将unsigned int崩溃会导致循环崩溃?

时间:2019-07-17 08:30:32

标签: c++ for-loop

以下程序会产生意外结果

#include <iostream>
using namespace std;

int main() {
    for(unsigned int i = 10; i >= 0; i--)
    {
        cout << i << endl;
    }
    return 0;
}

但将unsigned int更改为int会得到输出10,9,8 ...,0

拥有unsigned int并使用它来遍历值[n,0](含)的正确方法是什么?我迭代数组的每个元素,但不想使用foreach语法,因为我需要一个变量来保存元素的位置。

3 个答案:

答案 0 :(得分:3)

无符号变为负数,不正确。无符号算术运算会回绕,因此在无符号算术运算中,如果从零减去1,则将得到最大的无符号值。这是什么取决于您的编译器,但是如果您具有32位整数,则为4294967295。

我不认为您的程序应该崩溃,我认为它应该永远循环,因为在无符号算术i >= 0中总是正确的。

顺便说一句,我编写该循环以使其正确使用无符号算术的方式是

for (unsigned int i = 11; i-- > 0; )
{
    cout << i << endl;
}

答案 1 :(得分:1)

如果程序崩溃,则表明编译器有缺陷。

unsigned减少为零会产生该类型的最大数目。

成语

for (unsigned i = 11; i-->0; )

(当与您出现的循环体一起使用时,将输出整数10, 9, ..., 0

尽管正在过时,但在使用unsigned类型时经常使用

-->本身并不是真正的运算符,因为它被解析为两个单独的标记-->,但有时也称为 slide运算符,特别是像我这样的老年人。

答案 2 :(得分:1)

我认为您的困惑与for循环的运作方式有关。在这里您可以找到description。重要的细节是了解每次循环

for (init_statement; condition; iteration_expression){ statement;}

正在运行,操作顺序等效于以下内容:

{
 init_statement 
 while ( condition ) { 
  statement 
  iteration_expression ; 
 }
}

这意味着在{strong> 循环块执行后,i会减小。

对于int,当i = 0时,它将运行其中的代码,然后减小该值。这样,循环的下一次迭代将使条件失败,因此它不会显示i = -1

关于unsigned int,它永远不会变成负数。如果您对其进行调试,则将看到它达到0时如何将值转换为无符号值而不是值-1,而结果是一个很大的正值。特别是如果unsigned int为32位,则为4294967295。您可以查看详细信息in this other question

这就是为什么您具有“意外行为”(不适用于编译器)的原因,因为突然间您有一个非常大的正数,因此您手中可能会有无限循环。