c语言指针变量类型导致的问题?

void main()
{

    double * p;
    int * k;
    int t=55;

    p = &t;
    k = &t;
    printf("%d %d\n",*p,*k);
}

为什么输出 *p=55 *k=4201104 为什么*k变成了内存地址呢? 如果先输出*k 后输出*p 结果是正常的 求解

阅读 2.7k
3 个回答

C 语言有一种叫做未定义行为(Undefined behavior)的东西。意思是,你不要这样写,如果你这样写了,我就不能保证会发生什么了。

这个,使用一个 double 指针去解引用一个 int 变量是一个未定义行为(strict aliasing rule)。

[[ Note

使用 %d 来输出一个 double (*p) 是另一个。C11(draft) 7.21.6.1(THe fprintf function)/9

9 ...... If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined

End Note]]

换句话说,未定义行为是一些编译器无法检测的“错误”。(现在的编译器已经可以检测到一些了,比如用 %d 输出 double 在适当的编译选项下,会被 gcc 据掉。)如果程序里有未定义行为,那么程序结果就不能保证/不可预测。C 语言只能保证没有未定义行为的程序有可预测的结果。保证程序没有未定义行为是程序员的责任。

输出的时候应该会去转换 通过内存地址找到对应的55.当先打印K的时候。因为K 也是int指针,所以指向了t=55的内存地址,然后P的地址也是K的地址所以都是55. 而如果先打印P的话。因为P是double. 而t=55是int 指针,类型不对。他会截断/调整。

因为int是4字节,double是8字节,从int*地址读取8字节内存会带有4字节垃圾数据。printf接收到的参数内存是char*/55/..../55,把垃圾数据[....]解析成整型自然会得到错误的结果。如果仅传递低4字节就可以得到正确的结果了printf("%d %d\n",*(int*)p,*k);