您的位置:首页 > 其它

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

2015-10-27 14:01 375 查看
问:能否像下边这样用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了!
结束
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: