这段代码是什么意思?我的意思是,似乎我们取一个变量的地址并将其转换为(指针类型),之后我们将其引用,因为我们将知道该值。我错了吗?
#include "stdio.h"
int main(void) {
int numI = 3;
float numF = * (float *)&numI;
printf("%f", numF);
numF = 3.0;
numI = * (int*)&numF;
printf("\n%d", numI);
return 0;
}
答案 0 :(得分:2)
请考虑以下步骤:
numI
和numF
是两个碰巧在您的架构上具有相同大小的对象,即4个字节。&numI
是类型为int *
的表达式,其值为对象numI
的地址。(float *)&numI
投射它是float *
类型的表达式,具有相同的值。为了告诉编译器,这个地址是float
的地址。*(float *)&numI
会生成float
类型的值,该值取决于值int
的{{1}}的实际表示形式。例如,在intel核心处理器(小端,32位,2s补码)上,地址3
的字节将包含intI
。 03 00 00 00
对象使用IEEE-756标准在同一处理器的内存中表示:float
代表非常小值 1.5 x 2 -148 < / sup> ,大约 4.2039e-45 。03 00 00 00
,首先将其转换为printf
类型,具有相同的值,double
将值转换为printf
,因为格式为{{ 1}}仅指定6个小数位且没有指数。为了获得更精确的转化,您可以使用生成0.000000
的{{1}}或生成十六进制表示%f
的{{1}}。%g
的{{1}}值4.2039e-45
重新解释为%a
,生成值0x1.8p-148
。以下是程序的修改版本,使其更加明确:
float
输出:
3.0F
但请注意:
00 00 40 40
和int
在内存中的表示是特定于体系结构的。一些系统表示具有大端字节顺序的1077936128
,一些系统具有填充位和陷阱值,一些复古系统甚至使用一个补码或符号+幅度表示。尽管大多数当前系统使用与整数相同的字节排序的IEEE-756,但#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
int main(void) {
int numI;
float numF;
unsigned char *p;
assert(sizeof numI == sizeof numF);
numI = 3;
p = (unsigned char *)&numI;
printf("int value %d is represented in memory as %02X %02X %02X %02X\n",
numI, p[0], p[1], p[2], p[3]);
//numF = *(float *)&numI;
memcpy(&numF, &numI, sizeof numF);
printf("reinterpreted as float with format %%f: %f\n", numF);
printf("reinterpreted as float with format %%g: %g\n", numF);
printf("reinterpreted as float with format %%a: %a\n", numF);
printf("numF exact value: %g * 2^-148\n", numF * pow(2.0, 148));
numF = 3.0;
p = (unsigned char *)&numF;
printf("float value %.1g is represented in memory as %02X %02X %02X %02X\n",
numF, p[0], p[1], p[2], p[3]);
//numI = *(int *)&numF;
memcpy(&numI, &numF, sizeof numI);
printf("reinterpreted as int with format %%d: %d\n", numI);
printf("reinterpreted as int with format %%#X: %#X\n", numI);
return 0;
}
的表示可能更具异国情调。因此,您的程序再次具有未定义的行为,并且最多会产生特定于实现的输出。int value 3 is represented in memory as 03 00 00 00
reinterpreted as float with format %f: 0.000000
reinterpreted as float with format %g: 4.2039e-45
reinterpreted as float with format %a: 0x1.8p-148
numF exact value: 1.5 * 2^-148
float value 3 is represented in memory as 00 00 40 40
reinterpreted as int with format %d: 1077936128
reinterpreted as int with format %#X: 0X40400000
复制字节,如修改后的代码所示。现代编译器将为此生成非常有效的代码,将int
扩展到仅仅2条指令,如果不是更少。