C++ 从double开始施放总是返回零

C++ 从double开始施放总是返回零,c++,c,gcc,clang,C++,C,Gcc,Clang,为什么下面的代码在使用clang编译时返回零 #include <stdint.h> uint64_t square() { return ((uint32_t)((double)4294967296.0)) - 10; } 我本以为double会变成零(整数),而负号会把它包围起来。换句话说,为什么不管要减去哪个数,它总是产生零呢?请注意,gcc确实会产生不同的数字,正如预期的那样: push rbp mov rbp, rsp mov

为什么下面的代码在使用clang编译时返回零

#include <stdint.h>
uint64_t square() {
    return ((uint32_t)((double)4294967296.0)) - 10;
}
我本以为double会变成零(整数),而负号会把它包围起来。换句话说,为什么不管要减去哪个数,它总是产生零呢?请注意,gcc确实会产生不同的数字,正如预期的那样:

    push    rbp
    mov     rbp, rsp
    mov     eax, 4294967285
    pop     rbp
    ret

我假设将4294967296.0强制转换为
uint32\t
是未定义的行为,但即使如此,我也希望为不同的子帧生成不同的结果。

将超出范围的
双精度
强制转换为
无符号类型的行为确实未定义

环绕不适用于无符号类型,即使是
无符号
类型

这是一条经常被遗忘的规则

一旦程序控制到达一个未定义的结构,整个程序就是未定义的,甚至有些矛盾的是,已经运行的语句


参考资料:

g++5.4.0给出了4294967285(-11个无符号),因此编译器需要如何处理未定义的行为

__Z6squarev:
LFB1023:
        .cfi_startproc
        pushl   %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        movl    $-11, %eax
        movl    $0, %edx
        popl    %ebp
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc

是未定义的行为,但即使如此,我也希望是
-不。如果某个东西是未定义的行为,你不会期望。你不能期望。它几乎是这样定义的-如果某个东西是未定义的行为,你不能期望代码做任何事情。顺便说一句,
(double)
“cast”在这里什么都不做,因为该文本已经是
double
类型。与未定义的行为一样,未定义如果系统每次遇到未定义的行为时表现不同,那就太好了。这是A-应该发生的,当然,除了你不能依赖行为不同之外:如果你试图利用它,一个DS9K会使你的代码被遮挡。请指定你是否想要C回答或者C++答案。尤其是在强制转换和未定义行为方面,这些语言差异很大,通常不应被视为相同的语言。可能需要添加源代码:
__Z6squarev:
LFB1023:
        .cfi_startproc
        pushl   %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        movl    $-11, %eax
        movl    $0, %edx
        popl    %ebp
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc