指针作为形参如何改变实参指针指向的地址?
首先给出结论:需要借助二级指针。
下面以交换两个数的值的问题为例来进行说明:问题:a = 5,b = 6;*pa=&a,*pb=&b,通过调用子函数交换两个指针的值(即使交换后,*pa输出6,*pb输出5)。
ps:虽然直接在主函数中进行交换很便捷,不会涉及到二级指针的问题。但我就是想实现调用函数进行交换^ ^。
以调用函数的方法实现时,经常会出现以下常见错误。
//文字乏味,可以先看图片和原理分析
错误做法:
问题:a = 5,b = 6;*pa=&a,*pb=&b,通过调用子函数交换两个指针的值(即使交换后,*pa输出6,*pb输出5)。
下面给出常见的错误代码:
#include<bits/stdc++.h>
using namespace std;
void swap2(int *t1,int *t2)
{
printf("---swap2---start---:t1自身地址%p t2自身地址%p\n",&t1,&t2);
printf("---swap2---start---:t1指向地址%p t2指向地址%p\n",t1,t2);
int *temp;
temp = t1;
t1 = t2;
t2 = temp;
printf("---swap2---end---: t1指向地址%p t2指向地址%p\n",t1,t2);
}
int main()
{
int a=5,b=6;
int *pa,*pb;
pa = &a,pb = &b;
printf("a自身地址:%p b自身地址:%p\n",&a,&b);
printf("(主函数中)交换前:pa指向地址:%p pb指向地址:%p\n",pa,pb);
printf("(主函数中)交换前:pa自身地址:%p pb自身地址:%p\n",&pa,&pb);
//swap1(&pa,&pb);
swap2(pa,pb);
printf("(主函数中)交换后:pa指向地址:%p pb指向地址:%p\n",pa,pb);
printf("(主函数中)交换后的a,b值:%d %d",*pa,*pb);
return 0;
}
运行结果图:
可以看到,pa和pb指向地址并没有发生变化,因此输出的值依旧是5 6
错误原因分析:
形参和实参的关系是地址不同而值相同。
指针里面存放的值是地址,在swap2(pa,pb);时,传入t1的只是- -存放在pa里面的a的自身地址,而不是pa本身的地址。相当于t1 copy了 pa的值,t1和pa是独立的,因此在函数swap进行交换操作时,t1和t2互换值并不影响pa和pb。
图示如下图所示(图示的地址值和上图运行结果已对应):
正确做法:
问题:a = 5,b = 6;*pa=&a,*pb=&b,通过调用子函数交换两个指针的值(即使交换后,*pa输出6,*pb输出5)。
#include<bits/stdc++.h>
using namespace std;
void swap1(int **t1,int **t2)
{
printf("swap1--start--*t1=pa指向地址:%p t1指向地址:%p *t2=pb指向地址:%p t2指向地址:%p\n",*t1,t1,*t2,t2);
int *temp;
temp = &(**t1);
*t1 = &(**t2);
*t2 = temp;
/*int **temp;
temp=(int**)malloc(sizeof(int));
*temp = &(**t1);
*t1 = &(**t2);
*t2 = *temp;*/
printf("swap1--end--pa指向地址:%p t1指向地址:%p pb指向地址:%p t2指向地址:%p\n",*t1,t1,*t2,t2);
printf("swap1--a,b值:%d %d\n",**t1,**t2);
}
int main()
{
int a=5,b=6;
int *pa,*pb;
pa = &a,pb = &b;
printf("a自身地址:%p b自身地址:%p\n",&a,&b);
printf("(主函数中)交换前:pa指向地址:%p pb指向地址:%p\n",pa,pb);
printf("(主函数中)交换前:pa自身地址:%p pb自身地址:%p\n",&pa,&pb);
swap1(&pa,&pb);
//swap2(pa,pb);
printf("(主函数中)交换后:pa指向地址:%p pb指向地址:%p\n",pa,pb);
printf("(主函数中)交换后的*pa,*pb值:%d %d",*pa,*pb);
return 0;
}
运行结果图:
可以看到,pa和pb的指向地址已经在主函数中也交换成功,故而可以输出交换后的值6,5。
正确原理分析:
既然错误原因已经分析出,传入swap函数的参数是pa存储的地址(即&a),而不是pa的本身地址(即&p)。那么我们把pa,pb的自身地址传给形参不就好了。
通过二级指针t1,t2来访问到pa,pb,进而交换pa和pb存储的地址值。
步骤如下(指针的存储地址,自身地址都与上图运行结果已对应):
- temp = &(**t1);设置临时变量 *temp,存储t1指向地址的指向地址的地址(即&a)
- 令 *t1 = &(**t2);
其中 *t1 意义就是 t1指向地址(pa自身地址0069FF04)存储的值(0069FF0C,即&a),直白的来说: *t1就是pa。
其中 &(**t2)就是b的地址,即&b。
故这步的意思就是,让指针pa指向b。 - 令 *t2 = temp;
意义是让pb存储a的地址,即pb指向a。
图示如下(指针的存储地址,自身地址都与上图运行结果已对应):
2020.09.25更新
由于本人水平有限,难免有错误疏漏之处,欢迎批评指正