void指针的转换(2)

来源:互联网 发布:网络视频广告表现形式 编辑:程序博客网 时间:2024/06/07 21:01
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类型指针所指向的数据一直都在内存中存放着,并没有被改动,而只是我们在引用时从内存中提取数据的过程中发生了提取错误。道理很简单,一个有两字节组成的数据,而你非要提取一字节,是有可能发生错误的(但不是一定会发生错误,当一个数据既能用一字节表示,又能用两字节表示时就不会产生错误)。如果我们提取正确的话,随时都可以得到正确的数据,比如将上面的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
0 0