为什么C语言的内存字段通过投值重解不同于普通投值和通过指针投值?

问题描述 投票:1回答:1

我写了这样的代码例子。

int main(void) {
     double f = 0.1;
     int i, j;

     i = *(int *)(&f);
     j = (int)f;
     printf("%d\n%d\n", i, j); 

     return 0;
}

我希望结果是一样的。因为我以为一般情况下这些都是一样的:把一种类型的数据重新解释为另一种类型的数据,并把一种类型的指针,投向另一种类型的指针,然后访问数据。但是我得到了。

-1717986918
0

原因是什么?对不起,如果很明显的话。

c casting reinterpret-cast
1个回答
2
投票
j = (int)f;

这得到的 价值f 并以某种方式将其转换为一个整数值。

i = *(int *)(&f);

这就是 地址f 并告诉编译器 "这是一个整数",然后将其值存储到 i.

第二种形式适用于原始位,而不考虑到双数在内存中的表示方式与整数不同。

编辑

正如Christian Gibbons所指出的,这种通过不同类型的指针访问对象的方式是 未定义行为这意味着你的应用程序可能会做各种意想不到的事情,即使运行良好;)


0
投票

只是补充@Ripi2的回答。

第一种情况是执行一个 转换 因此二进制的表示方法也不同。例如,数字 3.141516 有位代表 3 和一些位代表 .141516. 当你投向一个int时,编译器会简单地丢弃小数部分的位,并使用剩余的位作为整数的最低符号位。因此你得到的是 "3"。

对于用户定义的类型,实际上你可以 自主转换 运营商。你所要做的就是 正在创建一个 operator SomeType() const 方法。例如,如果你的类中有一个 operator int() const 方法,那么当你把你的类的对象投向一个 int (包括当你把对象传递给一个期望为int的函数时)。当然,该语言已经包含了对普通数据的有效转换,例如从浮点到整数的转换。

另一方面,如果你把一个指针从一种类型转换为另一种类型,编译器将不会执行任何转换。当你推导指针时,它只会把位于该位置的位作为你所要求的类型的二进制表示,并向你显示结果,如果你把它投射到它不是的东西上,结果可能是任何东西。这与使用 reinterpret_cast 而不知道自己在做什么。

© www.soinside.com 2019 - 2024. All rights reserved.