有些人可以解释一下这个C程序的行为我试图理解它的行为......
#include<stdio.h>
float x = 3.33,*y,z;
int *a,b;
int main() {
a = (int *)&x;
b = (int)x;
y = (float *)a;
z = (float)b;
printf("\nOriginal Value of X: %f \ncasting via pointer A:%d and back Y: %f \ndirect casting B:%d and back Z:%f\n",x,*a,*y,b,z);
}
输出:
Original Value of X: 3.330000
casting via pointer A:1079320248 and back Y: 3.330000
direct casting B:3 and back Z:3.000000
好的,为什么A
的值为1079320248
而且它不是一些随机值,X = 3.33
的值始终相同,如果X
更改为某些值,则会更改不同的价值我期待A
之类的东西是3
,但不是。{/ p>
答案 0 :(得分:3)
在您的代码中没有“通过指针A'进行投射”。您只是强制编译器将 [1] NA NA NA NA NA NA NA NA 742.5581 915.8140 1099.0698 1292.3256
[13] 1375.5814 NA NA 1625.3488 1828.6047 2041.8605 2265.1163 2378.3721 NA NA 2718.1395 2831.3953
[25] 2944.6512 3057.9070 3171.1628 NA NA 3510.9302 3624.1860 3737.4419 3850.6977 3963.9535 NA NA
[37] NA NA NA NA NA NA
指向浮点值,其中假定它指向一个整数。
使用Reymond Chen在评论部分中指出的page,我们得到3.33的二进制表示形式:
a
现在,使用this页面查找其等效的32位有符号整数。你会得到01000000010101010001111010111000
,这是让你困惑的非随机数字。
如果这对你没有任何意义,那就让我说清楚一点吧。 1079320248
和a
都指向相同的二进制值y
,它表示两个不同的值(3.33为float,1079320248为int),具体取决于您告诉编译器使用的数据类型为了它。
<强>更新强>
仅为了学术兴趣,如果您希望printf语句为01000000010101010001111010111000
打印3,请将第三个参数替换为:
A
答案 1 :(得分:2)
TL; DR 将指针转换为不同的非兼容类型并返回然后访问最后一个是OK,当您尝试使用不兼容类型的中间指针时问题就开始了
详细说明,您的代码会导致undefined behavior,因为您违反了严格的别名规则。
引用C11
,章节§6.5
对象的存储值只能由具有其中一个的左值表达式访问 以下类型: 88)
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本
- 对应于有效类型的有符号或无符号类型 对象,
- 对应于合格版本的有符号或无符号类型的类型 有效的对象类型,
- 包含其中一种上述类型的聚合或联合类型 成员(包括,递归地,子集合或包含的联合的成员),或
- 字符类型。
所以在你的情况下,对于像
这样的定义 float x = 3.33,*y,z;
//....
a = (int *)&x;
b = (int)x;
y = (float *)a;
您首先将指向float
的指针转换为整数指针,然后将其转换回float *
并根据章节§6.3.2.3/ P7中提到的规则
指向对象类型的指针可以转换为指向不同对象类型的指针。如果 对于引用的类型,结果指针未正确对齐 68),行为是 未定义。 否则,当再次转换回来时,结果应该等于 原始指针。 [...]
因此,访问y
很好,但不是a
。您将面临对齐不匹配,从而导致UB。不要试图这样做。尊重类型。