C语言学习---通过指针形参修改实参的值/交换两个数字的值---原理深究

C语言学习—通过指针形参修改实参的值/交换两个数字的值—原理深究

要通过函数调用修改实参的值,首先我们要明白函数调用过程中的传参方式返回方式

传参方式:在c语言里面,所有的参数传递都是单向的值传递,就算是我们常说的地址传递,其本质上也是一种值传递,不过地址传递传递的是一串地址数字

返回方式:我所总结的返回方式有两种,一种是可以返回主函数的,一种是无法返回主函数的,具体如下:
比如我们常用的递归调用

int func(int n){
    int sum;
    if(n<0)printf("请输入大于0的整数!");
    else if(n==1||n==0)sum=1;
    else sum=n*func(n-1);
    return sum;
}
int main(){
    int num,multi;
    int func(int n);
    scanf("%d",&num);
    multi=func(num);
    printf("%d",sub);
}

func函数里面的临时变量sum,是我们创建出来的,可以直接返回主函数,而func函数里面的形参n,虽然系统调用函数时也会创建’'n"这个临时变量,但是这个形参是无法返回的,这个形参的改变也影响不到主函数里面实参num的值
相信大家已经了解到我想说的了,我总结出来的,这个临时变量能不能返回,看的就是这个临时变量是谁创建的
好,那我们接下来步入本博文的重点,关于如何调用函数来修改主函数里实参的值

通过不调用函数的思路,我们可以总结出三种貌似可行的方法:

  1. 调用函数—实参本身改变
  2. 调用函数—指针指向改变<即修改指针变量的值>
  3. 调用函数—指针指向的变量改变

我们先来看第一种方法——调用函数—实参本身改变

int main(){
    int x=3,y=4;
    change(x,y);
    if(x==3&&y==4)printf("修改失败!");
    else if(x==4&&y==3) printf("修改成功!");
    return 0;
}
int change(int a,int b){
    int temp;
    temp=a;
    a=b;
    b=temp;
}

结果如下:修改失败! Process returned 0 (0x0) execution time : 0.316 s Press any key to continue.

这是为什么呢?首先我们知道,函数实参传参过去之后,系统会自动创建两个形参a和b,a和b的值即x与y的值,但是当change函数执行完成之后,a和b这两个变量会被释放,而x与y则毫无改变,用一张图解释这个过程:
方法1
接下来我们来看第二种方法—调用函数—指针指向改变<即修改指针变量的值>

int main(){
    int x=3,y=4,*point_1=&x,*point_2=&y;
    change(point_1,point_2);
    if(x==3&&y==4)printf("修改失败!");
    else if(x==4&&y==3) printf("修改成功!");
    return 0;
}
int change(int *p1,int *p2){
    int *temp;
    temp=p1;
    p1=p2;
    p2=temp;
}

结果如下:修改失败! Process returned 0 (0x0) execution time : 0.310 s Press any key to continue.
这又是为什么呢?原因很简单,这一思路是改变指针的指向,也就是改变指针变量存的地址,而这个指针变量的值也是一个实参,而形参本身是无法改变实参的,引文函数调用过程的数据传递是单向的值传递,具体原理如下图所示:
方法2
可见,形参中p1与p2确实成功地交换了指向,**但是!**当函数调用完成后这俩是要被释放掉的,而point_1与point_2根本没有改变

最后我们来看第三种方法——调用函数—指针指向的变量改变

int main(){
    int x=3,y=4,*point_1=&x,*point_2=&y;
    change(point_1,point_2);
    if(x==3&&y==4)printf("修改失败!");
    else if(x==4&&y==3) printf("修改成功!");
    return 0;
}
int change(int *p1,int *p2){
    int temp;
    temp=*p1;//*p1=x
    *p1=*p2;
    *p2=temp;
}

结果如下:修改成功! Process returned 0 (0x0) execution time : 0.290 s Press any key to continue.

可以看到我们修改成功了,那到底是为什么呢?我们用一个代码检验这个过程:

int main(){
    int a,b,*p1,*p2;
    scanf("%d %d",&a,&b);
    p1=&a;
    p2=&b;
    printf("修改前地址:%d %d\n",p1,p2);
    printf("修改前a:%d,b:%d\n",*p1,*p2);
    change(p1,p2);
    printf("修改后地址:%d %d\n",p1,p2);
    printf("修改后a:%d,b:%d\n",*p1,*p2);
    return 0;
}
int change(int *p1,int *p2){
    int temp;//不能用*temp?--------初始未赋值,值不可预见,这个未知单元可能存储着一个有用的数据,就可能对整个系统的正常工作造成破坏
    temp=*p1;//*p1=a
    *p1=*p2;
    *p2=temp;
}

运行结果如下:

3 4
修改前地址:6422028 6422024
修改前a:3,b:4
修改后地址:6422028 6422024
修改后a:4,b:3

Process returned 0 (0x0)   execution time : 2.220 s
Press any key to continue.

可见,整个过程中两个实参的地址并无任何改变,改变掉的是地址内存储的值,也就是调用函数改变掉了指针指向的变量,用一个图解释整个过程:
方法3
由此可见,要调用函数修改实参的值,必须通过指针,并且形参指针要修改的是地址内存储的值

  • 12
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值