In the following code:
#include <iostream>
int main()
{
const long l = 4294967296;
int i = l;
return i; //just to silence the compiler
}
the compiler warns about implicit conversion (using -Wall and -std=c++14) as following:
warning: implicit conversion from 'const long' to 'int' changes value from 4294967296 to 0 [-Wconstant-conversion]
which is ok. But there is no warning if the conversion is from double to int, as in the following code:
#include <iostream>
int main()
{
const double d = 4294967296.0;
int i = d;
return i; //just to silence the compiler
}
Why the compiler reacts differently in these situations?
Note 1: clang version is 3.6.2-svn240577-1~exp1
Note 2: I've tested it with many others versions of gcc, clang and icc thanks to Compiler Explorer (gcc.godbolt.org). So all tested versions of gcc (with exception of 5.x) and icc threw the warning. No clang version did it.
The conversion from double
to an integer type changes the value "by design" (think to 3.141592654
converted to an int
).
The conversion from long int
to int
instead may or work or may be undefined behavior depending on the platform and on the value (the only guarantee is that an int
is not bigger than a long int
, but they may be the same size).
In other words the problems in the conversions between integer types are incidental artifacts of the implementation, not by-design decisions. Warning about them is better especially if it can be detected at compile time that something doesn't work because of those limitations.
Note also that even conversion from double
to int
is legal and well defined (if done within boundaries) and an implementation is not required to warn about it even when the loss of precision can be seen at compile time. Compilers that warn too much even when the use could be meaningful can be a problem (you just disable warnings or even worse get the habit of accepting a non-clean build as normal).
These implicit conversion rules may add up with other C++ wrinkles getting to truly odd-looking and hard to justify behaviors like:
std::string s;
s = 3.141592654; // No warnings, no errors (last time I checked)
Don't try to use too much logic with C++. Reading specs works better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With