float f = 12.5;
unsigned int _f = *reinterpret_cast<int*>(&f);
std::cout << _f << std::endl; // result: 1095237632
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下这种铸造的原理吗?代表_f什么?
编辑
所以我1095237632转换为二进制后得到的这个数字是0b1000001010010000000000000000000,这个二进制数字是12.5在IEEE-754中。我说对了吗?
没有人可以解释(*),因为它不起作用。
来自cppreference:
与static_cast不同,但与const_cast不同,reinterpret_cast表达式不会编译为任何CPU指令(在整数和指针之间进行转换时,或者在指针表示形式取决于其类型的晦涩架构上除外)。它纯粹是一个编译时指令,它指示编译器将表达式视为具有new_type类型。
使用reinterpret_cast只能进行以下转换,除非这种转换会消除常量性或易变性。
然后遵循一系列规则,涵盖允许重新解释强制类型转换的内容。将类型A转换为完全不相关的类型B不在其中,并且您的代码表现出不确定的行为。
(*)严格来说是不正确的。您将float视为一个int,如果您查看它们在硬件上的表示形式,并且检查编译器的输出,则可以弄清楚为什么获得值,尽管未定义行为是未定义的,因此不值得输入详细信息除非您愿意编写不可移植的代码。
我们来看两个函数。其中之一定期将 float 转换为 int ,其中之一使用 reinterpret_cast 重新解释它:
int cast_to_int(float f) {
// Rounds f to an int, rounding towards 0
return (int)f;
}
int reinterpret_cast_to_int(float i) {
// Just copies the bits
return *reinterpret_cast<int*>(&i);
}
Run Code Online (Sandbox Code Playgroud)
那么到底发生了什么?我们来看看装配图:
cast_to_int(float):
cvttss2si eax, xmm0 // We cast to an int
ret
reinterpret_cast_to_int(float):
movd eax, xmm0 // We directly copy the bits
ret
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,有一条执行转换的汇编指令:
cast_to_int(0.7) -> 0
cast_to_int(1.0) -> 1
cast_to_int(1.5) -> 1
cast_to_int(2.1) -> 2
Run Code Online (Sandbox Code Playgroud)
在第二种情况下,reinterpret_cast只是直接转换位的底层表示。它实际上没有做任何事情,该函数只是将输入寄存器复制到输出寄存器。
在幕后,floats 的位表示与ints 非常不同,这就是为什么你会得到奇怪的数字。