溢出 int 时 cin 的意外行为
Unexpected behavior from cin when overflowing int
全部,我这里有一些我无法解释其行为的代码。它发布在下面。我查看了 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(溢出整数),那么第一个输出将显示 "Value of x = -2147483648",第二个输出将显示 "Value of x = 2147483647"。 cin.fail() 也将 return 为真。 cin 对输入做了什么?我认为如果 cin.fail() 为真,那么 x 的值应该不受影响。如果不受影响,我希望 x 的值会正常溢出(就像 scanf 那样)。这里的 cin 是怎么回事?为什么将值限制为整数最大值?
提前致谢!
您的 scanf
:C++ 中溢出有符号整数类型的行为是 未定义。推测引擎盖下发生的事情是毫无意义的。 "Overflow as normal"特别没有意义。
您的 cin
:C++03 之前的版本,如果无法容纳输入,x
将不会更改。因此,后续 cout
的行为将是 undefined 因为您将读回未初始化的变量。从 C++03 开始,如果超出范围,x
的上限(或下限)为最大(或最小)值。这就是你的第二种情况。
在 C++98 中,当输入失败时变量没有改变。如果您尝试输入未初始化的变量,这是一个缺点。
例如:
int a;
cin >> a;
cout << a; // UB if input failed!
在以后的标准中,当输入超出该范围时,变量将设置为可能的最大值或最小值。
对于 operator>>(int& val)
,标准表示 [istream.formatted.arithmetic]:
The conversion occurs as if performed by the following code fragment (using the same notation as for
the preceding code fragment):
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);
全部,我这里有一些我无法解释其行为的代码。它发布在下面。我查看了 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(溢出整数),那么第一个输出将显示 "Value of x = -2147483648",第二个输出将显示 "Value of x = 2147483647"。 cin.fail() 也将 return 为真。 cin 对输入做了什么?我认为如果 cin.fail() 为真,那么 x 的值应该不受影响。如果不受影响,我希望 x 的值会正常溢出(就像 scanf 那样)。这里的 cin 是怎么回事?为什么将值限制为整数最大值?
提前致谢!
您的
scanf
:C++ 中溢出有符号整数类型的行为是 未定义。推测引擎盖下发生的事情是毫无意义的。 "Overflow as normal"特别没有意义。您的
cin
:C++03 之前的版本,如果无法容纳输入,x
将不会更改。因此,后续cout
的行为将是 undefined 因为您将读回未初始化的变量。从 C++03 开始,如果超出范围,x
的上限(或下限)为最大(或最小)值。这就是你的第二种情况。
在 C++98 中,当输入失败时变量没有改变。如果您尝试输入未初始化的变量,这是一个缺点。
例如:
int a;
cin >> a;
cout << a; // UB if input failed!
在以后的标准中,当输入超出该范围时,变量将设置为可能的最大值或最小值。
对于 operator>>(int& val)
,标准表示 [istream.formatted.arithmetic]:
The conversion occurs as if performed by the following code fragment (using the same notation as for the preceding code fragment):
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);