问题描述
有人告诉我,类型转换C ++转换只会改变系统解释信息的方式(例如,将char
'A'
转换为int
会返回65
自{以来使用cout
打印时
记忆保持为01000001
)。
但是,我注意到,当将浮点数转换为相同宽度的整数时,该值将被保留且不会更改,就像仅更改解释一样。
例如,让X
为双精度浮点数:
double X = 3.14159;
就我现在而言,在检查&X
时,我们会发现(由decimal to binary converter转换):
01000000 00001001 00100001 11111001 11110000 00011011 10000110 01101110
但是,正如您中有些人已经知道的那样,当您这样做:
long long Y = (long long)X;
Y
将是3
的截断版本X
,而不是4614256650576692846
,它是查看{{1}的二进制值时得到的值},如果要寻找&X
。
因此,我认为很明显它们是错误的,但是,铸造在低层级如何工作?是否检测到该值是否会更改?您将如何编码它以获得long long
而不是Y = 4614256650576692846
?
解决方法
铸造将尝试保留尽可能精确的值。
您可以使用memcpy()
复制位推特。
#include <iostream>
#include <cstring>
int main() {
double X = 3.14159;
long long Y;
memcpy(&Y,&X,sizeof(Y));
std::cout << Y << '\n';
return 0;
}
,
通过投射,编译器可以决定如何更改数据,以使其尽可能有用,同时又尊重所请求的数据类型。
从int
到char
的转换只是将解释从65
更改为'A'
。
但是,当我们有一个需要保留的值时,编译器将使用特殊的指令进行转换。
例如,当从double
转换为long long
时,处理器将使用CVTTSD2SI
指令,该指令将FP寄存器的值装入并截断为通用的值:
double a = 3.14159;
long long b = (long long)a;
将进行反汇编(为了便于理解,我摆脱了堆栈指针):
movsd xmm0,QWORD PTR [a]
cvttsd2si rax,xmm0
mov DWORD PTR [b],rax
因此,使用原始值的方法将如所选答案中所述:取消引用double
的指针并将其放入long long
变量中,或者如其他所述,使用memcpy ()。
如果您想获得Y = 4614256650576692846
,可以使用:
double X = 3.14159;
long long Y = *( (long long*)(&X) );
这会将双指针转换为长的长指针,然后编译器认为(long long*)(&X)
在长的长存储区中。
但是我不建议您这样做,因为结果基于double
在计算机上的存储方式,因此不能保证结果为4614256650576692846。