c语言 通过调用函数交换两个实参指针的指向地址

指针作为形参如何改变实参指针指向的地址?

        首先给出结论:需要借助二级指针


下面以交换两个数的值的问题为例来进行说明:问题: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存储的地址值。
步骤如下(指针的存储地址,自身地址都与上图运行结果已对应):

  1. temp = &(**t1);设置临时变量 *temp,存储t1指向地址的指向地址的地址(即&a)
  2. 令 *t1 = &(**t2);
    其中 *t1 意义就是 t1指向地址(pa自身地址0069FF04)存储的值(0069FF0C,即&a),直白的来说: *t1就是pa。
    其中 &(**t2)就是b的地址,即&b。
    故这步的意思就是,让指针pa指向b。
  3. 令 *t2 = temp;
    意义是让pb存储a的地址,即pb指向a。

图示如下(指针的存储地址,自身地址都与上图运行结果已对应):
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


2020.09.25更新

由于本人水平有限,难免有错误疏漏之处,欢迎批评指正

  • 28
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值