Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

combination of unary minus and float conversion

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?

like image 373
zrnzvxxy Avatar asked Jul 12 '13 09:07

zrnzvxxy


1 Answers

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.

like image 113
devnull Avatar answered Nov 04 '22 08:11

devnull