先说结论:一级指针做函数参数,只能改变其所指地址中存储的变量的值,无法改变指针本身的值,即不能改变原实参的指向;
二级指针做函数参数,仍然无法改变指针本身的值,但是可以改变二级指针指向的一级指针的指向。
一级指针做函数参数,传入的是原来指针的副本,也就是形参的地址和原来实参地址是不同的,但形参和实参的值(也就是指向的地址一样),所以可以在函数内部改变指向地址所存储的变量。
#include<iostream>
using namespace std;
void func1 (int x) {
int tmp = x;
x = tmp + 1;
}
void func2 (int* x) {
cout << "x: " << x << ", *x: " << *x << ", &x: " << &x << endl;
int tmp = *x;
*x = tmp + 1;//改变指针所指向地址内存储变量的值,没有改变指针本身的内容
}
void func3 (int** x) {
int tmp = **x;
**x = tmp + 1;
}
int main()
{
// int a,b;
// while(cin>>a>>b)cout<<(a+b)<<endl;
int a = 1;
int* b = &a;//b存的是a的地址,也就是b=&a
int** c = &b;//c存的是b的地址,也就是c=&b; a=*b=**c
cout << "a: " << a << ", &a: " << &a << endl;
cout << "b: " << b << ", *b: " << *b << ", &b: " << &b << endl;
cout << "c: " << c << ", *c: " << *c << ", **c: " << **c << endl;
func2(b);
cout << "b: " << b << ", *b: " << *b << ", &b: " << &b << endl;
cout << "c: " << c << ", *c: " << *c << ", **c: " << **c << endl;
return 0;
}
运行结果
可以看到在func2内输出的&x和 main中的&b不相等,在退出func2后,形参int* x的内存被释放,但是我们已经通过他改变了形参指向的地址0x7ffc3b4b572c中存储的a的值。
既然可以这么改,为什么还要引入二级指针呢?
上面说到,在func2内输出的&x和 main中的&b不相等,在退出func2后,形参int* x的内存被释放,如果我们在func2内部改变形参指针x本身的值,也就是改变他的指向,main中实参b的值会不会改变呢?答案是否定的,我们来验证一下。
上面我们在func2中令tmp=2,让x指向tmp,但是after *b和**c都没有改变。原因是退出func作用域,形参x已经被销毁,b的值本身没有被改变,函数内部也没有去改变b指向的内容。
如果想在函数内改变指针的指向该怎么做呢,二级指针就可以做到:
#include<iostream>
using namespace std;
void func1 (int x) {
int tmp = x;
x = tmp + 1;
}
void func2 (int* x) {
cout << "func2 ing" << endl;
cout << "x: " << x << ", *x: " << *x << ", &x: " << &x << endl;
static int tmp = *x;
tmp ++;
cout << "tmp: " << tmp << ", &tmp: " << &tmp << endl;
// *x = tmp + 1;//改变指针所指向地址内存储变量的值,没有改变指针本身的内容
x = &tmp;//改变指针的指向
}
void func3 (int** x) {
cout << "func3 ing" << endl;
cout << "x: " << x << ", *x: " << *x << ", &x: " << &x << endl;
static int tmp = **x;//写成static是因为,如果非static,后面*b和**c就是野值,因为tmp退出作用域被销毁了
tmp ++;
cout << "tmp: " << tmp << ", &tmp: " << &tmp << endl;
*x = &tmp;
}
int main()
{
// int a,b;
// while(cin>>a>>b)cout<<(a+b)<<endl;
int a = 1;
int* b = &a;//b存的是a的地址,也就是b=&a
int** c = &b;//c存的是b的地址,也就是c=&b; a=*b=**c
cout << "before" << endl;
cout << "a: " << a << ", &a: " << &a << endl;
cout << "b: " << b << ", *b: " << *b << ", &b: " << &b << endl;
cout << "c: " << c << ", *c: " << *c << ", **c: " << **c << ", &c: " << &c << endl;
// func2(b);
func3(c);
cout << "after" << endl;
cout << "b: " << b << ", *b: " << *b << ", &b: " << &b << endl;
cout << "c: " << c << ", *c: " << *c << ", **c: " << **c << ", &c: " << &c << endl;
return 0;
}
运行结果:
以上内容只是个人测试分析得到的,如果有误辛苦指正~