溢出int时来自cin的意外行为

时间:2016-03-09 17:50:48

标签: c++ overflow cin

所有,我在这里得到了一些我无法解释其行为的代码。它发布在下面。我看了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(一个溢出int),那么第一个输出将说&#34;值x = -2147483648&#34;第二个输出将表示&#34;值x = 2147483647&#34;。 cin.fail()也会返回true。 cin对输入做了什么?我认为如果cin.fail()为true,则x的值应保持不受影响。如果不是不受影响,我会期望x的值正常溢出(就像scanf那样)。 cin在这里发生了什么?为什么将值加到整数最大值?

提前致谢!

2 个答案:

答案 0 :(得分:4)

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

例如:

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

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

对于operator>>(int& 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);

答案 1 :(得分:2)

  1. 您的scanf:在C ++中溢出有符号整数类型的行为是 undefined 。推测引擎盖下发生的事情是毫无意义的。 “正常溢出”尤其毫无意义。

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