函数调用时,需注意实参和形参的类型差异,类型内存存储格式的差异

问:能否像下边这样用void **指针作为参数,使函数模拟按引用传递参数吗?

         void f(void **);

         double *dp;

         f((void **)&dp);

答:不可移植,这种代码可能有效,而且有时鼓励这样用,但前提是所有指针的内部表示都是一样的,也即内存中数据存储格式一样。

         C语言中没有通用指针类型,void *之所以可以用作通用指针,是因为当它和其他类型相互赋值的时候,如果需要,它可以自动转换成其他类型。但是,void **就不会自动转换了,原因是,当你使用void **指针的时候,例如用*操作符访问void **所指向的void *值得时候,编译器无法知道void *值是否从其他类型的指针转换而来,从而,编译器只能认为它仅仅是个void *指针,所以程序就无法正确访问到想要的结果。

         换言之,你使用的任何void **值必须是某个位置的void*值得地址,(void **)&dp这样的类型转化虽然能编译通过,但执行结果可能不是我们想要的。如果void **指针指向的不是void *类型,并且这个类型的大小和内存表示和void *也不同,则程序就无法正确访问到此类型。

         如何让上面代码正确工作呢,我们要使用void*类型做一下中转:

 

         void f(void **);

         double *dp;

         void *vp = dp;//可以这样直接复制,编译器会自动帮我们类型转换

         f(&vp);

         dp = vp;//同上

 

据我所知,上面的情形不常见,但是会有,下面再看一个常见的,容易犯错误的例子:

         void incme(double *p){

                   *p +=1;

                   printf(“value =%lf\n”, *p);

}

int main(int argc, char **argv){

int i=1;

incme((double *)&i);

return 0;

         }

此程序的结构一定不是我们想要的结果。这是因为变量i所在内存空间中存放的是有符号整形的格式,这是板上钉钉的事。此时,incme函数中要用的类型是double的,我们知道double在内存中的格式和int的不同,所以意想不到的结果就产生了。如何修改呢?和前提到过一样用一个中转:

         void incme(double *p){

                   *p +=1;

                   printf(“value =%lf\n”, *p);

}

int main(int argc, char **argv){

int i=1;

double d=i;

incme(&d);

i=d;

return 0;

         }

 

这样修改后就OK了!

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值