繁体   English   中英

C/C++ casting在底层做了什么?

[英]C/C++ What does casting do in the low level?

有人告诉我,类型转换 C 转换只会改变系统解释信息的方式(例如,在使用cout打印时,将char 'A'转换为int确实返回65 ,因为在 memory 中它保持为01000001 )。

但是,我注意到,当将浮点数转换为相同宽度的整数时,该值是守恒的并且没有改变,就像只改变解释一样。 例如,设X为双精度浮点数:

double X = 3.14159;

就我现在而言,在检查&X时我们会发现(由十进制转换为二进制转换器):

01000000 00001001 00100001 11111001 11110000 00011011 10000110 01101110

但是,正如你们中的一些人已经知道的那样,在执行以下操作时:

long long Y = (long long)X;

Y将是3 ,即X的截断版本,而不是4614256650576692846 ,如果查找long long ,它会在&X处查看二进制值时获得的值。

所以,我认为很明显他们错了,但是,铸造在低水平上是如何工作的? 是否检测到该值是否会更改? 您将如何对其进行编码以获得Y = 4614256650576692846而不是Y = 3

转换将尝试尽可能精确地保留值。 您可以使用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;
}

转换让编译器决定如何更改数据,以便它在尊重请求的数据类型的同时尽可能有用。

intchar的转换只是将解释从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     QWORD PTR [b], rax

因此,使用原始值的方法将如所选答案中所述:取消引用指向double的指针并将其放入long long变量中,或者如其他所述,使用 memcpy()。

如果你想得到Y = 4614256650576692846 ,你可以使用:

double X = 3.14159;
long long Y = *( (long long*)(&X) );

这会将双指针转换为一个 long long 指针,然后编译器认为(long long*)(&X)是一个 long long 存储的地方。

但我不建议你这样做,因为结果取决于你机器上double的存储方式,并不能保证结果是 4614256650576692846。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM