我有代码:
int a = 1065353216;
int* pa = &a;
printf("%d", *((float*)pa)); // Выводит 0
为什么输出为0?我理解sizeof(int*) == sizeof(float*),也就是考虑了4个字节的信息,但是这个信息的二进制表示被解释为整数,那么输出应该是1065353216,有什么问题?
PS二进制表示:
1065353216: 00111111 10000000 00000000 00000000(1.0 代表 IEEE754 代表浮点数)
本质上,您的代码执行以下操作:
那些。您正在尝试执行以下操作:
并且
0
仅因为您没有传递 int 而返回,即 这是一种指示错误的方法类型不匹配会导致未定义的行为。
gcc
cprintf
将类型转换float
为double
,然后打印。编码 :
汇编:
结论 :
关联 :
https://godbolt.org/z/6on83T
由于在第一个
printf
编译器没有将数字加载到寄存器esi
中,因此将打印一个随机数。不同的编译器是不同的。首先,您的程序的行为是未定义的,因为它违反了严格的别名。您不能像引用类型对象
int
一样引用类型对象float
。其次,您的程序的行为是未定义的,因为
printf
传递给函数的参数与使用的转换说明符不匹配。该函数printf
期望接收int
并且您传递一个类型的参数double
。第三,即使前两个 UB 按预期工作,您也不遵守默认参数Promotions 。type 参数
float
转换为 typedouble
。所以在这一行中,printf("%d", *((float*)pa));
函数printf
实际上获取了类型的值,double
并尝试输出 8 字节参数的前 4 个字节(假设类型int
占用 4 个字节,类型double
占用 8 个字节)。如果传递的类型值为
double
,1.0
则 64 位浮点数的尾数的所有 52 位为零。这意味着前四个字节很可能也等于零(如果构成类型对象的字节double
以某种不寻常的顺序存储,则可能不等于零)。示例:
结论:
因此,您的代码在解析时
UB
等效于以下内容: