我有一个void
指向内存地址的指针.然后,我做
int
pointer = void
指针
float
pointer = void
指针
然后,取消引用它们获取值.
{ int x = 25; void *p = &x; int *pi = p; float *pf = p; double *pd = p; printf("x: n%d\n", x); printf("*p: %d\n", *(int *)p); printf("*pi: %d\n", *pi); printf("*pf: %f\n", *pf); printf("*pd: %f\n", *pd); return 0; }
解除引用pi
(int
指针)的输出为25.但解除引用pf
(float
指针)的输出为0.000.dereferncing pd
(double
指针)输出一个不断变化的负分数?
为什么这和字节序有关(我的CPU是小端)?
按照C
标准,你允许转换任何指针void *
并将其转换回来,它将具有相同的效果.
引用C11
,章节§6.3.2.3
[...]指向任何对象类型的指针可以转换为指向
void
和返回的指针; 结果应该等于原始指针.
这就是为什么当你将void指针转换为int *
,取消引用并打印结果时,它会正确打印.
但是,标准并不保证您可以取消引用该指针为不同的数据类型.它本质上是调用未定义的行为.
所以,解引用pf
或pd
获得float
或者double
是不确定的行为,因为你想读分配的内存int
为一个float
或double
.有一个明显的mismtach案例导致UB.
详细说明,int
和float
(和double
)具有不同的内部表示,因此尝试将指针转换为另一种类型,然后尝试取消引用以获取其他类型的值将不起作用.
相关的C11
,章节§6.5.3.3
[...]如果操作数的类型为''指向类型'',则结果的类型为''type''.如果为指针分配了无效值,
*
则未定义一元运算符的行为.
对于无效价值部分,(强调我的)
在由一元*运算符解除引用指针的无效值中,有一个空指针,一个与指向的对象类型不适当对齐的地址,以及一个对象在其生命周期结束后的地址.