Consider the following C statements:
unsigned long x = 1;
float a = -x;
double b = -x;
I would expect the unary minus term to yield an unsigned long value equal to ULONG_MAX and a and b to be set to single and double precision representations of ULONG_MAX, respectively.
This is the result I obtain with gcc 4.4.7 on 32-bit Linux and with the Intel and PGI compilers on 64-bit Linux. With gcc (tested versions 4.4.7, 4.7.2 and 4.8.0, both with -O0 and -O2) on 64-bit Linux, however, the double variable b has the expected value, but float a becomes equal to -1 instead.
By contrast, the following statements will set both a and b to floating point representations of ULONG_MAX on all compilers and systems I tested:
unsigned long x = 1;
unsigned long y = -x;
float a = y;
double b = y;
If I use unsigned int instead of unsigned long, I get the expected result on all systems, too.
Is this some kind of undefined behaviour or a compiler error?
This is due to a bug in GCC -- the type conversion happens before the negation.
The issue seems to be have been around for a while. Bug 55771 - Negation and type conversion incorrectly exchanged
In your second example, the negation happens before the type conversion. As such, you see expected results.
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