当>>时会发生什么运算符是否尝试输入大于变量可以包含的值?

时间:2017-01-12 20:47:44

标签: c++ arrays ifstream integer-overflow

我从文本文件中提取数字并用它们填充int类型的数组。

我将这些值插入到数组中,同时使用这些代码行循环遍历.txt文件(其中k是.txt文件中的数字量):

java.sql.SQLSyntaxErrorException: ORA-00904: "Child2_"."childId3": invalid identifier;

当文本文件中的数字小于2,147,483,647时,这是整数类型的最大大小,一切顺利。

当数字大于此值时,我认为程序溢出并且无法插入但是之后也无法插入任何数字。

导致溢出发生后不再插入数字的原因是什么?

3 个答案:

答案 0 :(得分:5)

标准要求如果输入值超出范围,则将最近的可用值写入目标,并设置流的failbit。具体要求(来自[istream.formatted.arithmetic] / 3)是:

operator>>(int& val);
     

转换发生时好像由以下代码片段[...]执行:

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);

一旦设置了流的failbit,它就会“粘滞”,所以进一步尝试提取数据都会立即失败,直到故障清除被清除。

答案 1 :(得分:5)

std::istream& std::istream::operator>>(std::istream&, int&)上,cppreference说:

  

表现为FormattedInputFunction。构造并检查可能跳过前导空格的sentry对象后,通过调用std::num_get::get()提取整数值

     

...

     

如果提取失败,则将零写入值并设置failbit。如果提取导致值太大或太小而无法拟合,则会写入std::numeric_limits<T>::max()std::numeric_limits<T>::min()并设置failbit标志。 (自c ++ 11起)

这不是规范性的,但它确实提供了对此处发生的事情的正确总结。

FormattedInputFunctions将从流构造一个哨兵并检查该值。如果岗哨对象的评估结果为false,则为no input is performed

如果,among other situations,正在操作的流设置了故障点,则哨兵对象将评估为false

所以,发生了什么:

  1. 流尝试读取的整数太大而无法保存在int数据类型中。
  2. 传入其功能的int设置为int可存储的最大可能值。
  3. 传入函数的流已设置其failbit。
  4. 对流的进一步读取失败并且什么也不做,因为设置了流的failbit。
  5. 您可以通过在执行读取操作后检查整数的failbit和值来检测这些溢出错误,如问题Read int from istream, detect overflow的已接受答案中所述。

    您可以通过使用std::basic_ios::clear 取消设置 failbit来从这些错误中恢复。在调用clear取消设置failbit之后,进一步的读取将按预期运行。

答案 2 :(得分:-5)

未定义的行为。算术溢出可能会被默默地忽略,或者可能会引发信号,从而终止程序,具体取决于实现的质量。