今天我想向大家介绍形参传一级地址还是二级地址的情况。
首先,来个栗子
void change(int *p) 地址:3000>>2000 5 地址:2500
{ 变量:p 变量:*p
p = (int *)malloc(sizeof(int));
*p = 5;
}
void main() 地址:2000
{ 变量:num
int num = 10;
change(&num);
printf("num = %d",num);
}
结果打印出来num = 10,子函数的调用并没有改变num的值,我们假设主函数变量地址为2000,子函数变量地址为3000,主函数中将num的地址当作形参传送给子函数,很明显,子函数的地址由3000变为2000,虽然子函数拥有了对子函数的控制权,但是num并没有出现修改成5的迹象。
这是当然了,因为子函数中重新申请了变量p的地址,这个地址并不是我们能控制的,假设申请到的地址是2500,那么*p = 5这条指令是存放在地址2500中的,跟子函数和主函数地址完全不一样啊。
所谓道高一尺魔高一丈,就是为了解决这种情况,便出现了形参为二级地址的方法,栗子如下:
void change(int **p) 地址:3000>>2010 5 地址:2500
{ 变量:p 变量:*p
*p = (int *)malloc(sizeof(int));
**p = 5;
}
void main() 地址:2000
{ 变量:num
int num = 10;
int *a = #
change(&a); 地址:2010>>2500
printf("num = %d",*a); 变量:*a
}
打印出来就是妥妥的num = 5了,原因也是之前讲到的地址问题,然而,这一个相比之前,就有些复杂了,跟上一个相比,区别在于子函数的形参由一级指针变成了二级指针,也正因为是二级指针的原因,主函数必须要定义一个指针变量*a存放变量num,再把*a的地址当作形参传给子函数,才是二级地址的格式。
假设*a的地址是2010,传给子函数,子函数变量的地址由3000变成2010,子函数中重新申请p的地址,此时*p = (int *)malloc(sizeof(int))中的*p就不是我们平时见到的指针变量了,而是二级指针的地址,假设申请到的同样是2500,是不是就可以得知*p = 2500,推算可得同时*p = &a,推算可得**p = *&a = a。
至此,便可知道,主函数变量*a的地址已经和子函数新地址2500一样了,那么地址2500中进行的**p = 5结果也会传给*a,*a的值就从10变成了5,完成了修改。
可能我说的有点啰嗦复杂了,那么来做一个简洁一点的小总结吧。
(1)子函数中改变普通变量的值,形参得用一级地址。
(2)子函数中改变指针变量的值,形参得用二级地址。