【问题标题】:Unexpected behavior from cin when overflowing int溢出 int 时 cin 的意外行为
【发布时间】:2016-03-09 17:50:48
【问题描述】:

所有,我这里有一些我无法解释其行为的代码。它张贴在下面。我查看了Why does integer overflow cause errors with C++ iostreams?,但它并没有真正回答我的问题。

#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
    int x;
    scanf("%d", &x);
    cout << "Value of x = " << x << endl;
    cin >> x;
    cout << "Failure Detected = " << cin.fail() << endl;
    cout << "Value of x = " << x << endl;
    return 0;
}

所以,我期望这段代码做的是读入一个整数,打印出该整数的值,读入另一个整数(到同一个变量中),然后打印出该整数。如果我输入 7 和 2,那么它会按预期工作。但是,如果我为第一个和第二个输入输入 2^31(整数溢出),那么第一个输出将显示“x 的值 = -2147483648”,第二个输出将显示“x 的值 = 2147483647”。 cin.fail() 也将返回 true。 cin 对输入做了什么?我认为如果 cin.fail() 为真,则 x 的值应该不受影响。如果不受影响,我希望 x 的值会正常溢出(就像 scanf 一样)。这里的cin是怎么回事?为什么将值限制为整数最大值?

提前致谢!

【问题讨论】:

  • 请不要因为显而易见而投反对票;这实际上非常微妙。

标签: c++ overflow cin


【解决方案1】:

在 C++98 中,输入失败时变量没有改变。如果您尝试输入未初始化的变量,这是一个缺点。

例如:

int a;
cin >> a;
cout << a;    // UB if input failed!

在以后的标准中,当输入超出该范围时,变量将设置为可能的最大值或最小值。


对于operator&gt;&gt;(int&amp; val),标准说 [istream.formatted.arithmetic]:

转换就像由以下代码片段执行(使用与 for 前面的代码片段):

typedef num_get<charT,istreambuf_iterator<charT,traits> > numget;
iostate err = ios_base::goodbit;
long lval;
use_facet<numget>(loc).get(*this, 0, *this, err, lval);
if (lval < numeric_limits<int>::min()) {
  err |= ios_base::failbit;
  val = numeric_limits<int>::min();
} else if (numeric_limits<int>::max() < lval) {
  err |= ios_base::failbit;
  val = numeric_limits<int>::max();
} else
  val = static_cast<int>(lval);
setstate(err);

【讨论】:

  • “标准变量将设置为可能的最大值或最小值”。标准是否规定了这一点?如果是这样,那么我的回答是不准确的。
  • 查了一下。你是对的。赞成(并为基本上窃取您的答案而道歉)。
【解决方案2】:
  1. 您的 scanf:在 C++ 中溢出有符号整数类型的行为是未定义。推测幕后发生的事情是毫无意义的。 “正常溢出”尤其没有意义。

  2. 您的cin:在 C++03 之前,如果无法容纳输入,x 将不会被更改。因此,后续 cout 的行为将是 undefined,因为您将读回未初始化的变量。从 C++03 开始​​,如果超出其范围,x 的最大值(或最小值)将被限制(或下限)。这就是您的第二种情况。

【讨论】:

    猜你喜欢
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-30
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多