> 文档中心 > C语言值传递和地址传递

C语言值传递和地址传递


C语言函数传参的两种方式


一. 值传递

我们举一个例子:

写一个函数找出两个整数中的最大值。

#include//get_max函数int get_max(int x,int y){  return (x>y)?x:y;}int main(){  int num1 = 10;  int num2 = 20;  int max = get_max(num1,num2);  printf("max = %d\n",max);  return 0;}

运行结果是:

max = 20

我们来分析一下这个函数调用过程:

num1,num2作为实参传入get_max()函数,形参x,y被实例化(分配内存单元),num1和num2的值按照函数形参表顺序对应地传给了x和y,也就是x=10,y=20,然后函数将x和y中较大的一个的值返回。函数调用完毕,x和y被自动销毁。

我们看一下函数的特征,如果函数的形参和实参一致,这就是值传递。

二.地址传递

再举一个例子:

写一个函数交换两个整形变量的内容。

很多初学者一看觉得太简单了,按照值传递我们来写一遍。

#include //值传递void Swap1(int x, int y) {    int tmp = 0;    tmp = x;     x = y;     y = tmp; }int main(){int num1 = 1;int num2 = 2;  printf("交换前::num1 = %d num2 = %d\n",num1,num2);  Swap1(num1, num2);printf("swap1::num1 = %d num2 = %d\n", num1, num2);return 0; }

但此时的结果是什么呢?

C语言值传递和地址传递

num1,num2值并没有变啊,并没有交换啊,为什么呢?

因为当实参传给形参的时候,形参是实参的一份临时拷贝,对形参的修改不会影响实参

我们来打印一下各变量的地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AnfGU4Nm-1642493097749)(../source/images/image-20220118153528486.png)]

可以看到,实参有自己的地址,形参也有自己的地址,实参只把自己的值传给了形参,地址各有各的,实参的地址上放的值并没有变啊,并且形参在函数调用完后就自动销毁了,也就是说函数内与函数外的变量并没有建立真正的实质的联系。就想象你copy了一个自己的仿生人,他吃了东西,进你的胃了吗?肯定他吃他饱,跟你毫无相关是吧(狗头

那么这个问题怎么解决呢?地址传递

#include //值传递void Swap1(int x, int y) {    int tmp = 0;    tmp = x;     x = y;     y = tmp;      } //地址传递void Swap2(int *px, int *py) {    int tmp = 0;    tmp = *px;     *px = *py;     *py = tmp; }int main(){    int num1 = 1;    int num2 = 2; printf("交换前::num1 = %d num2 = %d\n",num1,num2);    Swap1(num1, num2);    printf("Swap1::num1 = %d num2 = %d\n", num1,num2);    Swap2(&num1, &num2);    printf("Swap2::num1 = %d num2 = %d\n", num1, num2);    return 0; }

​ 我们来看一下结果
在这里插入图片描述

地址传递做了什么?

做地址传递时 函数参数是指针变量,指针变量里面装着的就是地址嘛,所以实参直接就把自己的地址传过去了,px里放的num1地址,py里放的num2地址, *px就是num1本身, *py就是num2本身,实参本身进行了赋值交换,这次不是你的仿生人了,就是你自己体验人生。

我们看一下函数特征:如果传入的实参是形参的指针,那就是地址传递。


其实有一个问题我好久才想明白:

为什么上一个例子(返回两数中较大的一个)没有用地址传递也成功了呢?这两种方式使用的界限是什么呢?

后来这个疑问终于被解答了:

因为第一个例子里num1,num2的值并不需要改变,函数中x,y比较后如果返回x,x的值和a的值是一样的,这个对结果是不影响的,也就是说,这种问题不需要改变实参的值,形参和实参不需要建立那么实质的联系

但要搞清楚的是,函数返回的是num1本身吗?是num1地址上的值吗?不,只是num1的拷贝x地址上的值

综上,在需要改变实参的值时一定要使用地址传递才行。


进行一个总结吧

1.值传递

​ 函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

2.地址传递
  • 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。

  • 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。

两种方式的辨别方法:如果函数的形参和实参一致,这就是值传递。如果传入的实参是形参的指针,那就是地址传递。


学习函数小TIP

  1. TDD测试驱动开发(Test driven development)

​ 先在main函数中写好函数怎么使用(测试),明确自己的需求,再根据需求写函数体

  1. 函数名

​ is_leap_year ✔️

​ IsLeapYear ✔️

​ Is_Leap_Year ❌不伦不类

  1. 函数最好只有功能,不要里面有多余的输出、格式,一个函数写出来是要大家都能调用的,最好具有通用性,多余的修饰在main函数中写好就行

安全期查询