将浮点转换为uint64和uint32的行为异常 当我将32位浮点转换成一个64位无符号整数的C++时,一切都如预期一样工作。 溢出导致设置FE_溢出标志(cfenv)并返回值0 std::feclearexcept(FE_ALL_EXCEPT); float a = ...; uint64_t b = a; std::fexcept_t flags; std::fegetexceptflag(&flags, FE_ALL_EXCEPT);

将浮点转换为uint64和uint32的行为异常 当我将32位浮点转换成一个64位无符号整数的C++时,一切都如预期一样工作。 溢出导致设置FE_溢出标志(cfenv)并返回值0 std::feclearexcept(FE_ALL_EXCEPT); float a = ...; uint64_t b = a; std::fexcept_t flags; std::fegetexceptflag(&flags, FE_ALL_EXCEPT);,c++,floating-point,type-conversion,C++,Floating Point,Type Conversion,但当我将32位浮点转换为32位无符号整数时,如下所示: std::feclearexcept(FE_ALL_EXCEPT); float a = ...; uint32_t b = a; std::fexcept_t flags; std::fegetexceptflag(&flags, FE_ALL_EXCEPT); 我的行为与64位转换的方式完全相同,只是上面的32位被截断了。 它等于: std::feclearexcept(FE_ALL_EXCEPT); float a = ..

但当我将32位浮点转换为32位无符号整数时,如下所示:

std::feclearexcept(FE_ALL_EXCEPT);
float a = ...;
uint32_t b = a;
std::fexcept_t flags;
std::fegetexceptflag(&flags, FE_ALL_EXCEPT);
我的行为与64位转换的方式完全相同,只是上面的32位被截断了。 它等于:

std::feclearexcept(FE_ALL_EXCEPT);
float a = ...;
uint64_t b2 = a;
uint32_t b = b2 & numeric_limits<uint32_t>::max();
std::fexcept_t flags;
std::fegetexceptflag(&flags, FE_ALL_EXCEPT);
std::feclearException(FE_ALL_除外);
浮动a=。。。;
uint64_t b2=a;
uint32_t b=b2&numeric_limits::max();
std::feexcept_t标志;
std::fegetexceptflag(&flags,FE_ALL_除外);
因此,只有当指数大于或等于64且 在指数32和64之间,它返回64位转换中较低的32位,而不设置溢出。 这是非常奇怪的,因为您会期望它在指数32处溢出

是应该这样,还是我做错了什么


编译器是:LLVM版本6.0(clang-600.0.45.3)(基于LLVM 3.5svn)

从浮点到整数的转换中溢出是未定义的行为。您不能依赖于使用单个汇编指令或溢出的指令来完成此操作,因为您希望为其设置溢出标志

可能已生成的汇编指令cvttsd2si在溢出时确实会设置标志,但在转换为32位int类型时可能会生成指令的64位变体。一个很好的理由是,当将浮点值截断为无符号32位整数时(如您的问题所述),因为目标寄存器的所有32个低位都被正确设置为在执行64位有符号指令后定义转换的浮点值。
cvttsd2si
指令没有无符号变量

从:

CVTTSD2SI使用截断标量双精度FP值将其转换为有符号整数

如果转换后的结果超出有符号双字整数的范围限制(在非64位模式或REX.W/VEX.W=0的64位模式下),则引发浮点无效异常,如果该异常被屏蔽,则返回不定整数值(80000000H)

如果转换的结果超过有符号四字整数的范围限制(在64位模式下,REX.W/VEX.W=1),则引发浮点无效异常,如果该异常被屏蔽,则返回不定整数值(80000000_00000000H)


这一点,尽管是针对C的,但在这个问题上进行了扩展。

无符号数字是否有溢出?或者它被称为溢出?当浮点数表示的数字与目标整数不匹配时,它是一个FE_溢出。