首页 文章

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

提问于
浏览
1

所有,我've got some code here that I can'解释行为 . 它发布在下面 . 我看了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()为true,则x的值应保持不受影响 . 如果不是不受影响,我会期望x的值正常溢出(就像scanf那样) . cin在这里发生了什么?为什么将值加到整数最大值?

提前致谢!

2 回答

  • 2

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

    例如:

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

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


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

    转换发生时好像由以下代码片段执行(使用与前面的代码片段相同的表示法):

    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);
    
  • 3
    • Your scanf :C中溢出有符号整数类型的行为未定义 . 推测引擎盖下发生的事情是毫无意义的 . "Overflow as normal"特别没有意义 .

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

相关问题