How floating point overflow is handled in iostreams

I have a very simple code:

#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; } 

When I compile this code with g ++ 4.1.2 and run it on Redhat 5.10 (the same compiler), I get the output:

 Conversion succeeded Conversion succeeded Conversion failed Conversion failed Conversion succeeded 1 2 0 17 17 12 

When I execute the same binary on Redhat Linux 6.5 (compiler 4.4.7), I get

 Conversion succeeded Conversion succeeded Conversion succeeded Conversion failed Conversion succeeded 1 2 0 1.79769e+308 12 

What is the expected behavior? An insufficient thread runs on 4.4.7, but 4.1.2 does not work. Overflow fails (but still changes the value) to 4.4.7 and will not work without changing anything to 4.1.2.

Is the behavior undefined or just incorrect for one or the other?

+8
c ++ iostream g ++
source share
1 answer

According to C ++ 11 22.4.2.1.2, the conversion should fail, but not overflow. In the event of an overflow, it should still give the value of the largest represented value, as well as the failbit setting.

So, your new compiler has the correct modern behavior.

However, both of your ancient compilers preceded C ++ 11 for many years. In earlier standards, a conversion was specified to give an error if scanf would; and do not give value in case of error. Moving to the C standard, scanf discards strtod , which in turn indicates an overflow error; but is there a stream error that is not valid for implementation.

So your old compiler is compatible with historical behavior.

+3
source share

All Articles