【问题标题】:Why does having unsigned int crash for loop on last iteration?为什么 unsigned int 在最后一次迭代中会导致循环崩溃?
【发布时间】:2019-07-17 08:30:32
【问题描述】:

下面的程序产生了意想不到的结果

#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 语法,因为我需要一个变量来保存元素的位置。

【问题讨论】:

  • 澄清一下,代码不会崩溃。它只是没有做你想做的事。

标签: c++ for-loop


【解决方案1】:

unsigned 变为负数,不正确。无符号算术环绕,所以在无符号算术中,如果你从零减一,你会得到最大可能的无符号值。这取决于您的编译器,但如果您有 32 位整数,那么它将是 4294967295。

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

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

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

【讨论】:

  • 说得对。那么在迭代器的类型为unsigned int的情况下,迭代[n,0]的正确方法是什么?
  • 我只是在答案中添加了一段以显示一种方式。
  • @john 很好的解决方法。但我想如果你想更明确的话,你也可以把i-- 放在iteration_expression 的位置。此外,如果您使用预增量运算符,这将失败,但 for (unsigned int i = 11; i &gt; 0; --i) 不会。对吗?
  • @VictorHMartin 该版本会给你不同的输出,11 降到 1,而不是 10 降到 0,因为你是在循环之后递减,而不是之前。
  • 啊,我现在明白了。感谢@john 的回答!
【解决方案2】:

如果您的程序崩溃,则意味着编译器有缺陷。

一旦unsigned 为零,就减少它会产生该类型的最大数量。

成语

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

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

在处理unsigned 类型时经常使用,尽管它已经过时了。 --&gt; 本身并不是一个真正的运算符,因为它被解析为两个单独的标记 --&gt;,但它偶尔被称为 slide 运算符,尤其是像我这样的老年人。

【讨论】:

  • 因为i是用来访问数组的
  • 啊,经典算子去
  • @northerner:是的,这可能是未定义的行为。
  • 您发布的惯用代码与 OP 使用的代码不同。特别是,您使用的是独占的&gt;,而不是包容的&gt;=
  • @KonradRudolph:我的代码从 10 到 0,包括 0。鉴于他们的循环是无限的,很难比较 OP 想要什么?
【解决方案3】:

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

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

运行时,操作顺序等价于:

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

这意味着i在for循环块执行后减少。

int 的情况下,当i = 0 时,它会运行其中的代码,然后减少值。这样,循环的下一次迭代就会使条件失败,因此它不会打印i = -1

关于unsigned int,它永远不会消极。如果您对其进行调试,您将看到,一旦它达到 0,而不是值 -1,该值将转换为无符号并且结果是一个很大的正值。特别是 4294967295,如果 unsigned int 是 32 位。您可以查看详情in this other question

这就是为什么你有“意外行为”(不是编译器),因为突然之间你有一个非常大的正数,所以你手上可能有一个无限循环。

【讨论】:

    猜你喜欢
    • 2022-07-14
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    相关资源
    最近更新 更多