作为将一些代码移植到Windows的一些工作的一部分,我遇到了一个问题,其中uint32_t最大值的转换 - >浮动 - >使用visual c ++构建时,uint32_t导致0。 我将问题归结为一个简单的程序,该程序在运行不同的编译器时显示问题。
#include <iostream>
#include <limits>
using namespace std;
int main()
{
uint32_t r1 = numeric_limits<uint32_t>::max();
float r2 = static_cast<float>(numeric_limits<uint32_t>::max());
uint32_t r3 = static_cast<uint32_t>(static_cast<float>(numeric_limits<uint32_t>::max()));
cout << "r1 = " << r1 << endl
<< "r2 = " << r2 << endl
<< "r3 = " << r3 << endl;
return 0;
}
当通过http://webcompiler.cloudapp.net/运行时,r3的输出为0,但是当通过https://ideone.com/ylf74N时,r3是最大值。
我猜测在转换回uint32_t时会发生+1,当它是UINT_MAX但是我想知道是否有人知道为什么或者究竟发生了什么?
答案 0 :(得分:2)
当从整数类型转换为实数类型时,结果可能是不精确的并且朝向真实类型中最接近的可表示(高于或低于原始值)四舍五入。在你的情况下,浮点数在其尾数部分有24位,因此,0xFFFFFFFF不会在转换中保持不变,因为它需要32位尾数。因此,它可以转换为0x100000000(最接近上方)。如果发生这种情况,您将从浮点数转换为0x100000000到32位无符号类型。此转换导致未定义行为(包括不可预测/不可靠的结果),因为该值超出了32位无符号类型的范围。
你也可以使用其他编译器获得UB,你只是没有意识到它。通过引入 volaitle (在r1,r2和r3的声明中)进行环境优化,你会看到它(ideone.com/1CCat8)。
答案 1 :(得分:1)
在您的系统上,似乎float
是32位类型,可能是IEEE754(但请注意标准并不坚持)。
numeric_limits<uint32_t>::max()
是4294967295。
这对你的漂浮来说太大了。 (IEEE754 32位浮点中可容纳的最大奇数是8388607)。
所以你的号码被四舍五入到4294967296.(这是可以容纳的壁橱号码。)
当然,将它转换回uint32_t
会导致它回绕到0。
对于其他系统,由于float
输出,我们知道sizeof
是32位。编译器正在进行错误优化。