关于函数用指针作为参数的易犯错误总结
前言:c
或c++
在函数中使用参数进行传递时,如果要想改变main
函数两个变量的值,此时就得用到将参数定义为指针的思想,然而在使用指针进行参数传递时,常常会导致错误,令人百思不得其解,下面我就个人的认知,使用函数交换两个数为例子,进行分析。
- 首先我们贴出正确写法:
void swap(int* a, int* b) {
int t = *a; *a = *b; *b = t;
}
int main() {
int a = 1, b = 2;
swap(&a, &b);
cout<<a<<" "<<b;
return 0;
}
分析:主函数定义两个变量a、b (即为a、b开辟了两块存储空间), 分别赋值为0、1(即将a、b存进相应的存储空间内),然后我们调用swap函数,将a、b的地址赋给新定义的a、b指针(注意:此时a、b与主函数的a、b截然不同)作为形式参数传递进去。在swap函数中,定义一个局部变量t,将指针a的值赋给t,再将b指针的值赋给a,最后将t的值赋给了指针b,完成了指针a与指针b进行值的交换,特别注意的是,本次变换只是值变换,其地址并没有发生变换。
我们将主函数a、b交换前,交换后的地址进行输出:
1 2
交换前:0x61ff1c 0x61ff18
交换后:0x61ff1c 0x61ff18
2 1
从中我们可以看出,用指针作为形参的实质:只是使指针的值发生改变,并没有使指针的指向(即地址)发生改变
- 补充:就指针的认识
定义一个指针:int* a;
我们可以将int*
看为一个整体,即int*
就是用来定义一个指针类型,跟’int、char、double’类型类似,此时,使用 a = &b;
就是将a指针指向b变量的地址(此时的a是一个指针,它必须用来指向某个地址或指向别的指针)。使用*a = b
就是将指针a地址所存储的值改为b(此时的*a是一个指针所指地址的值,相当于一个普通变量)。
- 初学者易犯的错误,容易写成
void swap(int* a, int* b) {
int* t = a; a = b; b = t;
}
分析:此写法首先定义一个局部指针t,使它指向指针,再将a指针指向b指针(将指针的值和地址都赋给a),最后将b指针指向t指针(同上)。这样一来,在这个函数体中,实现了a、b间 地址与值的同步修改,但这往往会导致一个误区:认为地址与值都修改了,那么a、b也实现了交换。其实这个交换只是在函数体内有效,在主函数中并没有真正实现a与b的交换。(这里很难想清楚,可以认为如果指针作为形参传递,在函数对指针的地址进行交换,可以看作是跟普通变量做形参一样,传递进来的只是地址的副本),总之,我们的一切还得回归到指针作为形参传递的实质:只是使指针的值发生改变,并没有使指针的指向(即地址)发生改变,即我们要进行的是对指针的地址值修改,而不是地址。
swap函数输出:
交换前:0x61ff1c 0x61ff18
交换后:0x61ff18 0x61ff1c
主函数输出:
1 2
交换前:0x61ff1c 0x61ff18
交换后:0x61ff1c 0x61ff18
1 2
可以看出,在主函数中a、b未能成功实现交换