函数传参——一级指针与二级指针
我们先来看一级指针作为参数:
float *s = NULL; //①
void fun(float *p1,float *p2, float *s) //②
{
s=(float *)calloc(1,sizeof(float)); //③
*s=*p1+*p2++;
}
调用函数fun(a, b ,s);
上述代码看似将一级指针s作为参数传入到fun函数内部,实际上并不是。因为①中的指针s与②中的参数指针不是一个同一个指针。如下图:
①中的指针s与②中的参数指针直接的关系如下:
由于fun函数中在堆空间中申请一块空间,关系如下:
从图中可以看到,fun()函数中的一级指针的指向被改变了。但是,无论我们在fun()函数中怎么折腾,始终都只能改变栈区指针的指向和堆空间中的值,而全局变量区中的指针的指向始终指向NULL,不会受丝毫改变。而且,当fun()函数执行完后,栈区中的一级指针就会被释放掉,那么此时我们也就再也无法寻找到这个一级指针指向的堆空间了。
这样的传参看似是地址传递,实际上它是值传递,因为它具有值传递的特性。
我们再来看一级指针地址(即二级指针)作为参数:
float *s; //①
void fun(float *p1,float *p2, float **s) //②
{
*s=(float *)calloc(1,sizeof(float)); //③
**s=*p1+*p2++;
}
调用函数fun(a, b ,&s);
我们可以看到,地址传递是一环扣一环。
二级指针**s保存的是全局变量区中一级指针*s的地址,所以,二级指针变量就指向全局变量区的一级指针。所以,fun()函数中,s表示的是栈区中的二级指针。而s的解引用*s,则表示的是二级指针指向的一级指针,注意:该一级指针是在全局变量区而不是在栈区。*s的解引用**s,就表示一级指针指向的空间。
fun()函数中, 语句:*s=(float *)calloc(1,sizeof(float)); ,申请一个堆空间,将堆空间的地址交给*s来保存,由上述所知,一级指针*s不是在fun()中,但是我们却可以通过对fun()函数内的二级指针s进行解引用,来改变栈区外面一级指针*s的指向。这个就是地址传递的特性。
所以,地址传递:
①对于普通变量,则用它的地址作为参数(即一级指针)。
②对于一级指针变量,则用它的地址作为参数(即二级指针)。
值传递与地址传递的区别就是,值传递,传递的是拷贝的数据副本。而地址传递,传递的则是变量所在的位置。
新世纪代码农场主: 我也想要
南桥北桥: 您用的这个查看库函数原型的文档怎么获取啊,能卖我一份吗
ttteapot: 妙啊 写得太好了 清晰易懂
m0_64179121: 你这个是标准库写的吗楼主
筱伟同学: 有没有spi的博客啊