C 当与浮点相乘时,无符号long是否会变为负数?

C 当与浮点相乘时,无符号long是否会变为负数?,c,implicit-conversion,C,Implicit Conversion,标题可能选错了,但我找不到一行好的摘要来回答这个问题。我的问题是我无法理解我的编译器在做什么,我想知道我是否在编译器中发现了一个bug。。。或者以我对C语言的理解 我的理解是: -1UL==ULONG\u MAX,这是安全的,因为无符号数字的溢出行为定义良好 乘积(-1UL)*1.0f涉及将左操作数转换为浮点,此转换保留除舍入错误以外的值(即ULONG_MAX) 到目前为止,我的编译器同意,除非1UL来自一个变量。这是我的测试程序,其输出为注释: #include <stdio.h&g

标题可能选错了,但我找不到一行好的摘要来回答这个问题。我的问题是我无法理解我的编译器在做什么,我想知道我是否在编译器中发现了一个bug。。。或者以我对C语言的理解

我的理解是:

  • -1UL==ULONG\u MAX
    ,这是安全的,因为无符号数字的溢出行为定义良好
  • 乘积
    (-1UL)*1.0f
    涉及将左操作数转换为浮点,此转换保留除舍入错误以外的值(即
    ULONG_MAX
到目前为止,我的编译器同意,除非
1UL
来自一个变量。这是我的测试程序,其输出为注释:

#include <stdio.h>

int main(void)
{
    unsigned long one = 1;
    unsigned long minus_one = - one;
    printf("%lu\n", - one);            // 18446744073709551615
    printf("%g\n", minus_one * 1.0f);  // 1.84467e+19
    printf("%g\n", (- one) * 1.0);     // 1.84467e+19
    printf("%g\n", (- 1UL) * 1.0f);    // 1.84467e+19
    printf("%g\n", (- one) * 1.0f);    // -1
    return 0;
}
#包括
内部主(空)
{
无符号长1=1;
无符号长减1=-1;
printf(“%lu\n”,-one);/18446744073709551615
printf(“%g\n”,减1*1.0f);//1.84467e+19
printf(“%g\n”(-one)*1.0);//1.84467e+19
printf(“%g\n”(-1UL)*1.0f);//1.84467e+19
printf(“%g\n”,(-one)*1.0f);//-1
返回0;
}
我无法理解最后的输出。我尝试了不同的优化级别和不同的语言标准(C90、C99和C11),得到了相同的结果。有人知道线索吗

环境:gcc 4.8.1/Ubuntu Linux 14.04/x86-64(I32LP64)


编辑:我刚刚注意到我的问题可能是重复的。

这似乎是gcc 4.8中的一个错误。我与您在4.8中的行为相同,但gcc 4.9和clang显示了正确的行为。

该程序在Visual Studio和我的VM(Ubuntu 10.04,gcc 4.4.3)中给出了预期的输出。您能验证它是一个bug吗?我可以是UB,在这种情况下,甚至4.8都是“正确的”。@user694733:它就在你引用的下一段中:如果转换的值在可以表示但不能精确表示的值范围内,那么结果就是最接近的较高值或最接近的较低的可表示值,以实现定义的方式选择。这似乎是正确的。如果该平台上的
long
为32位,则
float
应具有足够的范围,在这种情况下,UB被排除。
long
为64位,但仍在
float
的范围内。