两个变量的值进行交换时,需要用到一个临时变量储存其中一个变量的值。
那为什么第二段代码没有达到预期效果呢?用下面的代码结合注释进行解释。
#include <stdio.h>
void fun1(int* m, int* n);
void fun2(int* m, int* n);
void fun3(int** m, int** n);
int main()
{
int a = 1, b = 2; //a、b是整型变量
printf("调用fun1前,a=%d,b=%d\n", a, b);
fun1(&a, &b);
printf("调用fun1后,a=%d,b=%d\n", a, b);
int* pa = &a, * pb = &b; //pa、pb是整型指针变量
printf("调用fun2前,pa=%p,pb=%p\n", pa, pb);
fun2(pa, pb);
printf("调用fun2后,pa=%p,pb=%p\n", pa, pb);
int** ppa = &pa, ** ppb = &pb; //ppa、ppb是整型的二级指针变量(储存指针的地址)
printf("调用fun3前,pa=%p,pb=%p\n", pa, pb);
fun3(ppa, ppb); //或fun3(&pa, &pb);
printf("调用fun3后,pa=%p,pb=%p\n", pa, pb);
return 0;
}
//首先要明白,函数调用过程中,改变形参的值并不会影响实参的值
void fun1(int* m, int* n) //形参是a,b的指针
{
int t; //整型的值的交换
t = *m;
*m = *n;
*n = t; //虽然m,n是形参,但对m,n用*进行解引用,间接访问a、b的地址,修改了a、b的值
} //由此可知,要调用函数改变实参a、b的值,形参中要有它们的指针
void fun2(int* m, int* n) //形参是a,b的指针
{
int* t; //整型指针的值的交换
t = m;
m = n;
n = t; //形参的值交换了,但是没有间接访问pa、pb的地址,所以它们的值不会改变
} //根据fun1的例子可知,要调用函数改变实参pa、pb的值,
//形参中要有它们的指针,也就是指针的指针(二级指针)
void fun3(int** m, int** n)
{
int* t; //整型指针的值的交换
t = *m;
*m = *n;
*n = t; //虽然m,n是形参,但对m,n用* 进行解引用,间接访问pa、pb的地址,修改了pa、pb的值
} //综上所述,想通过调用函数改变某变量的值,则形参中需要有该变量的指针
如果对本回答有疑问,欢迎在回答下方评论!
如果本回答成功帮到你,麻烦动动手指点个采纳,谢谢啦~
因为改变形参的值不会改变实参的值
你设想如果第一个函数里面不是指针而是int m,int n,那你交换m和n的值会改变实参吗,不会吧
那第二个代码也一样啊,m和n是指针,你交换*m和*n,指针本身的值(地址)并没有改变,改变的是指向的内存里的值,而你交换m和n本身并不会对实参产生影响
你想要交换两个指针也可以哦
void fun(int **m, int **n)
{
int *t;
t = *m;
*m = *n;
*n = t;
}
int main()
{
int a,b;
int *pa=&a;
int *pb=&b;
fun(&pa,&pb); // 这样pa就指向了b,pb就指向了a
}
追加一下:
关于为什么要再引入一个变量的问题
假设这个函数不是inline的,那么传入的参数必然是两个变量的内存地址,那么在汇编层面就可能是这样的
mov eax, 参数m ; eax现在是m
mov edx, 参数n ; edx现在是n
mov ecx, [eax] ; 把m指向的那个值放到ecx
xchg ecx, [edx] ; 交换ecx和n指向的值
mov [eax], ecx ; 把n指向的那个值放到m指向的地址
// 这样就完成了一次交换
当然如果说这个函数是inline的,或者被编译器优化为自动inline了,那么如果m和n原来的值直接就在寄存器里,那根本不需要引入变量,直接xchg不就交换了吗?
总之这个引入第三变量交换两个变量的方法在逻辑上是完全正确的,具体会变成什么样子看编译器的选择了。
具体想知道编译器怎么做的可以反汇编看看,记住编译器开不开优化差别很大的。