我有一些非常简单的代码:
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
stringstream is("1.0 2.0 1e-500 1e500 12.0");
double d = {17.0, 17.0, 17.0, 17.0, 17.0};
for (int i=0; i < 5; ++i)
{
if (is >> d[i])
{
cout<<"Conversion succeeded"<<endl;
}
else
{
cout<<"Conversion failed"<<endl;
is.clear();
}
}
for (int i=0; i < 5; ++i) cout<<d[i]<<endl;
}
当我使用g ++ 4.1.2编译此代码并在Redhat 5.10(相同的编译器)上运行时,我得到输出:
Conversion succeeded
Conversion succeeded
Conversion failed
Conversion failed
Conversion succeeded
1
2
0
17
17
12
当我在Redhat Linux 6.5(编译器4.4.7)上执行相同的二进制文件时,我得到了
Conversion succeeded
Conversion succeeded
Conversion succeeded
Conversion failed
Conversion succeeded
1
2
0
1.79769e+308
12
预期的行为是什么?下溢在4.4.7上成功,但在4.1.2上失败。溢出在4.4.7上失败(但仍然改变了值)并且在4.1.2没有改变任何内容的情况下失败。
行为是否未定义或仅在一个或另一个上不正确?
答案 0 :(得分:3)
根据C ++ 11 22.4.2.1.2,转换应该是溢出失败,但不是下溢。在溢出的情况下,它仍应给出最大可表示值的值以及设置failbit
。
因此,您最近的编译器具有正确的现代行为。
然而,你的两个古代编译器都早于C ++ 11多年。在早期标准中,指定转换为scanf
时会出错;并且在出错时不给出值。转到C标准,scanf
遵循strtod
,后者又指定溢出错误;但是下溢是否存在错误是实现定义的。
因此,您的旧编译器与历史行为一致。