#include <stdio.h>
void print_binary(int n);
void test();
int main(){
test();
return 0;
}
void print_binary (int n){
unsigned int mask = 0;
mask = ~mask^(~mask >> 1);
for (; mask != 0; mask >>= 1){
putchar ((n & mask) ? '1' : '0');
}
}
void test(){
int x;
float *p;
p = (float *) &x;
printf ("x init value :%dn", x);
printf ("addr x and p are %p %pn", &x, p);
printf ("print x in bit ");
print_binary(x);
printf ("n");//00000000000000000000000000000000
*p = 6.35;
printf ("print x in bit ");
print_binary(x);
printf ("n");//01000000110010110011001100110011
printf ("x after 6.35 value :%dn", x);//1087058739
printf ("call1 x:%.100fn", x);//0.0000000.....
printf ("x:%dn", x);//1087058739
printf ("call2 x:%fn", x);//0.000000
printf ("p:%fn", *p);//6.350000
printf ("call3 x:%fn", x);//6.350000
}
结果:
x init value :0
addr x and p are 0x7ffc37d5ba8c 0x7ffc37d5ba8c
print x in bit 00000000000000000000000000000000
print x in bit 01000000110010110011001100110011
x after 6.35 value :1087058739
call1 x:0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
x:1087058739
call2 x:0.000000
p:6.350000
call3 x:6.350000
我在*p = 6.35;
后打印我的x
,并且 在内存中,我们得到01000000110010110011001100110011
,根据IEEE754,这是正确的数字, 有人可以解释为什么我的第一个printf ("call1 x:%.100fn", x)
打印我0.00...
, 但是我printf ("p:%fn", *p)
后,它可以打印6.35
吗?
取消引用p
是未定义的行为,因为p
不是指向float
,而是指向int
(例如。什么是严格的混叠规则?
此外,尝试使用"%f"
格式说明符打印int
是未定义的行为,因为该格式说明符需要double
(例如。为什么 printf("%f",0(;给出未定义的行为?
因此,您不能依赖此代码的任何行为 - 一切皆有可能。
在实践中,可能发生的事情是,编译器决定将*p = 6.35;
移动到printf ("p:%fn", *p);
之前。
从您的标签(类型转换和隐式转换(来看,您似乎期望发生某种类型转换。 事实并非如此。
使用类型错误的指针访问内存不会触发任何转换。它只是以不同的方式解释内存。这包括违反严格的别名规则,导致未定义的行为。
当您使用
printf ("call1 x:%.100fn", x);//0.0000000.....
你在欺骗你的编译器。 您承诺传递一个通常包含 8 个字节的double
值(%f
格式说明符(,但随后您只传递整数的 4 个字节。 类型说明符和参数类型的不匹配会导致未定义的巴哈维,所有的期望都是无所事事的。
然后你再用
printf ("p:%fn", *p);//6.350000
当您提供正确的双精度参数时,它工作正常。(这是唯一的隐式类型转换(
当您尝试编译此代码时,编译器应打印一些警告。 您应该始终侦听编译器并解决警告。