考虑以下C语句:
unsigned long x = 1;
float a = -x;
double b = -x;
我希望一元减项产生一个等于ULONG_MAX的无符号长值,a和b分别设置为ULONG_MAX的单精度和双精度表示。
这是我在32位Linux上使用gcc 4.4.7以及在64位Linux上使用Intel和PGI编译器获得的结果。但是,对于64位Linux上的gcc(测试版本4.4.7,4.7.2和4.8.0,都带有-O0和-O2),双变量b具有预期值,但float a等于-1代替。
相比之下,以下语句将在我测试的所有编译器和系统上将a和b设置为ULONG_MAX的浮点表示:
unsigned long x = 1;
unsigned long y = -x;
float a = y;
double b = y;
如果我使用unsigned int而不是unsigned long,我也会在所有系统上得到预期的结果。
这是某种未定义的行为还是编译器错误?
答案 0 :(得分:6)
这是由于GCC中的一个错误 - 类型转换发生在否定之前。
问题似乎已经存在了一段时间。 Bug 55771 - Negation and type conversion incorrectly exchanged
在你的第二个例子中,否定发生在类型转换之前。因此,您会看到预期的结果。
答案 1 :(得分:5)
您描述的是编译器错误。
(以下程序中没有未定义的行为来原谅编译器)
unsigned long x = 1;
float a = -x;
double b = -x;