void类型指针能够通过显式转换为具有更小或同样存储对齐限制的指针。但数据可能失真。所谓“同样存储对齐限制”是指void类型指针所指的数据在内存中所占的长度与显式转换后的指针所指的数据在内存中所占的长度相等,比方以上程序中的p1所指的原数据在内存中占2个字节,p2所指的数据在内存中也是占两个数据。
但应注意的是。仅仅有上面的这样的转换前后指针所指数据类型一致的转换才保持数据不失真,假设类型不一致,即使具有同样存储对齐限制,也有可能失真,比方由short转向unsigned short,请看下面程序:
#include<stdio.h>
int main(void)
{
short a=-5,*p1=&a;
unsigned short *p2;
void *p3;
p3=(void *)p1;
p2=(unsigned short *)p3;
printf("%d\n",*p2);
return 0;
}
其输出结果就不再是-5了。由于在指针转换时,short类型的数据也经过转换变成了unsigned short类型的数据,详细的转换过程请參考数据类型转换。
只是,也有数值不变的情况,如把a值变为5。
同理,假设是将void类型转换为具有更小存储对齐限制的指针时,也可能引起数值的改变。请看下面程序:
#include<stdio.h>
int main(void)
{
short a=720;
char *p1;
void *p2;
p2=(void *)&a;
p1=(char *)p2;
printf("%d\n",*p1);
return 0;
}
p1所指向的数据不再是720,而是-48。由于a的值720在内存中的表示形式为D0 02(十六进制表示,共两块,即两个字节),当中D0的地址即a的地址:0x0012ff7c。p2仅仅保存0x0012ff7c,不知道它占有两字节内存空间。而p1所指数据占有一字节。因此p1仅仅代表D0。无法代表D0 02。将D0翻译成有符号char类型,即-48(D0是补码)。当然。假设将a的值改为较小的数(-128~127)。如3,转换后的值变不会发生改变。
综上两种情况,事实上void类型指针所指向的数据一直都在内存中存放着,并没有被修改。而仅仅是我们在引用时从内存中提取数据的过程中发生了提取错误。道理非常easy,一个有两字节组成的数据。而你非要提取一字节,是有可能错误发生的(但不是一定会错误发生。当一个数据既能用一字节表示,又能用两字节表示时就不会产生错误)。假设我们提取正确的话。随时都能够得到正确的数据。比方将上面的printf("%d\n",*p1);改为printf("%d\n",*(short *)p1);则又会输出720。
3.假设将void类型的指针转换为具有更大存储对齐限制的指针时。则会产生无效值。例如以下面程序:
#include<stdio.h>
int main(void)
{
short a=23;
void *p1;
int *p2;
p1=(void *)&a;
p2=(int *)p1;
printf("%d\n",*p2); return 0;
}
其返回值为-859045865