C 函数的所有参数均以 “传值调用” 方式进行传递,这意味着函数将获得参数值的一份拷贝。这样函数就可以放心修改这个拷贝值,而不必担心会修改调用程序实际传递给它的参数。

既然调用函数时,函数只会得到参数的一份拷贝,那么在函数中处理这个参数,不会影响原来的参数值,也就是传递给它的参数值。

我们举个例子,奇偶检验的例子:

用函数实现这么一个功能,就是检验一个整数中的1的位的个数是偶数还是奇数?

/*
**对值进行偶校验
*/
int even_parity(int value, int n_bits)
{int parity = 0;/***计数值的值为1的位的个数*/while(n_bits > 0){parity += value & 1;value >> 1;n_bits -= 1; }//如果parity对2取余数为0,则返回TRUEreturn (parity % 2) == 0;}

这个例子说明了标量函数参数的传值调用行为。函数检查第一个参数是否满足偶校验,也就是它的二进制位模式中1的个数是否为偶数。

函数的第二个参数指定第一个参数中的有效位的数目。函数一次一位地对第1个参数值进行移位,所以每个位迟早都会出现在最右边的那个位置。所有的位逐个加在一起,所以在循环结束之后,我们就得到第1个参数值的位模式中1的个数。最后对这个数进行测试,看看它是否为偶数,如果是,返回TURE。

该函数对第一个参数值进行奇偶校验,函数处理的是第一个参数的拷贝,我们也确实感受到了处理的是参数值,确实是传值调用,但是这个例子并不能明显的或者没有体现出函数处理的是实际传递给函数的参数值的拷贝。

因此,我们再次举一个例子,说明这个问题。

写一个函数,用来交换调用程序中的两个整数值。


//交换调用程序中的两个整数void swap(int x, int y)
{int temp;   //中间值temp = x;x = y;y = temp;}

这个函数如果在程序中调用,可以放心地告诉呢,没有任何作用。

也就是说,并起不到交换两个参数值的效果。

原因也很简单,就是函数调用时,函数获得的是实际参数值的一份拷贝,并不会对传递给函数的实际参数值进行修改。


那么传说中的传址调用是什么情况呢?

C 的规则很简单:

所有参数都是传值调用。但是,如果被传递的参数是一个数组名,并且在函数中使用下标引用该数组的参数,那么在函数中对数组元素进行修改实际上修改的是调用程序中的数组元素。函数将访问调用程序的数组元素,数组并不会被复制。这个行为被称为“传址调用”。

上面所说的调用程序的意思是调用这个函数的程序,而不是函数本身。

数组参数的这种行为似乎与传值调用规则相悖。但是,此处其实并无矛盾之处。数组名的值实际上是一个指针,传递给函数的就是这个指针的一份拷贝。下标引用实际上是间接访问的另一种形式,它可以对指针执行间接访问操作,访问指针指向的内存位置。参数(指针)实际上是一份拷贝,但在这份拷贝上执行间接访问操作所访问的是原先的数组。

此处我们记住两个规则:

1. 传递给函数的标量参数是传值调用的;

2. 传递给函数的数组参数在行为上就像它们是传址调用的那样。

下面举个例子,这个例子有效地进行了整数之间的交换:

//交换调用程序中的两个整数void swap(int *x, int *y)
{int temp;temp = *x;*x = *y;*y = temp;}

在程序中调用这个函数,就可以有效的交换调用程序中的两个整数。

因为函数期望接受的参数是指针,所以我们应该按照下面的方式调用它:

swap(&a, &b);

一个例子不过瘾,那么再举一个例子:

这个例子是让编写一个函数,把一个数组中的所有元素设置为0:

//把一个数组的所有元素设置为 0void clear_array(int array[], int n_elements)
{//从数组的最后一个元素开始,逐个清除数组中的所有元素while(n_elements > 0)   //n_elements是数组中的元素的个数{array[--n_elements] = 0;}}

调用该函数时,传递给函数的第一个参数是一个数组名,该数组名相当于一个指针,实际上传递给函数的就是这个指针(数组名)的一份拷贝,下标引用实际上是间接访问的另一种形式,他可以对指针(地址)执行间接访问操作,访问指针指向的内存位置。这样就会改变调用程序中的数组值。

这个例子同时说明了另外一个特征。在声明数组参数时,不指定它的长度是合法的,因为函数并不为数组元素分配内存。间接访问操作将访问调用程序中的数组元素。这样,一个单独的函数可以访问任意长度的数组。

【 C 】函数参数通过传值调用还是传址调用?相关推荐

  1. JavaScript 函数参数是传值(byVal)还是传址(byRef)?

    对于"JavaScript 函数参数是传值(byVal)还是传址(byRef)"这个问题,普遍存在一个误区:number,string等"简单类型"是传值,Nu ...

  2. 简单了解函数的传值调用与传址调用(C语言)

    一.首先需要引入函数中的实际参数与形式参数 实际参数(实参)是指真实传给函数的参数.实参可以是常量.变量.表达式.函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值 ...

  3. 函数的调用(传值调用和传址调用)

    传值调用 函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参. 传址调用 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式. 这种传参方式可以让函数和函数外边的变量建 ...

  4. 手写C语言之函数概念-函数分类-实参与形参-传值调用与传址调用介绍(11)

    目录 函数是什么? C语言中函数的分类 库函数 自定义函数 写一个函数可以找出两个整数中的最大值. 交换整型变量的函数 函数的参数 实际参数(实参) 形式参数(形参) 函数的调用 传值调用 传址调用 ...

  5. 函数学习笔记(一) 传值调用、传址调用.

    前言  函数是程序的一个子程序,自己定义的函数与主函数的地位·相同. 函数分为: 库函数.自定义函数 一.库函数 在学习函数之前我们就有接触到了函数--库函数 比如说printf.scanf.getc ...

  6. 前端:JS/22/函数(函数的概念,函数的定义格式,函数定义格式的说明,函数的调用,函数的参数),全局变量和局部变量,拷贝传值和引用传址,匿名函数,二维数组,对象,自定义对象的创建

    函数 1,函数的概念 函数,是将一段公共的代码进行封装,给它起个名字叫"函数" 函数可以一次定义,多次调用:函数可以将常用的功能代码,进行封装,如:用户名的验证,验证码函数,邮箱验 ...

  7. JavaScript 是传值调用还是传引用调用?

    1. 例子 先来看两个个来自于 <JavaScript 高级程序设计>P70-P71 的两个例子. 1.1. 基本类型参数传递 function addTen(num) {num += 1 ...

  8. Java中的形参和实参的区别以及传值调用和传引用调用

    名词解析: 1.形参:用来接收调用该方法时传递的参数.只有在被调用的时候才分配内存空间,一旦调用结束,就释放内存空间.因此仅仅在方法内有效. 2.实参:传递给被调用方法的值,预先创建并赋予确定值. 3 ...

  9. Go 学习笔记(65)— Go 中函数参数是传值还是传引用

    Go 语言中,函数参数传递采用是值传递的方式.所谓"值传递",就是将实际参数在内存中的表示逐位拷贝到形式参数中.对于像整型.数组.结构体这类类型,它们的内存表示就是它们自身的数据内 ...

最新文章

  1. pikachu漏洞靶机之xss漏洞post提交方式
  2. CodeForces - 1316D Nash Matrix(构造+dfs)
  3. usb大容量存储设备驱动_usb无法识别怎么办 如何解决usb识别故障【详细步骤】...
  4. BZOJ4890 Tjoi2017城市
  5. vue 样式绑定 class
  6. 生信宝典被分享最多的15篇文章
  7. arraylist 初始化_ArrayList - 遍历ArrayList的三种方法
  8. 查不到元素_浓重中国元素游戏的本地化地狱
  9. 孙鑫MFC笔记之十三--多线程编程
  10. iOS进阶经常去的网站
  11. hive经典习题50题
  12. 算法 图4 哈利·波特的考试
  13. .vimrc快捷键设置
  14. Descriptive Essay文章内容怎么写?
  15. 硬件设计基础----MOS管
  16. mac(苹果)电脑有网,浏览器上不了网了,打开不了网页,但是微信、QQ正常使用,如何解决?
  17. Unity Flat Shading实现低多边形(low-poly)效果
  18. es - elasticsearch- search - DSL -specialized -percolate - 1
  19. JESD204接口调试总结——Xilinx JESD204B IP testbench解析
  20. 小型教育网站的开发与建设-总体设计(三)

热门文章

  1. .net Remoting(2)——信道,MarshalByRefObject类
  2. rocketmq怎么保证消息一致性_从入门到入土(三)RocketMQ 怎么保证的消息不丢失?...
  3. 通讯系统流程图_基于OBD系统的量产车评估测试(PVE)
  4. ecshop 解密index.php,ECShop 2.x 3.0代码执行漏洞分析
  5. linux64命令,每天一个Linux命令(64)shutdown命令
  6. redhat linux新建用户,linux redhat 添加用户
  7. 图书管理系统python怎么保存用户注册信息_Python实现图书管理系统
  8. 收音机磁棒天线4根接法_无线电科技基础:无声的海上GPS导航 天线接收的方向性...
  9. 清理svn信息_推荐候选人有奖啦~11.26最新招聘信息看这里!
  10. 语音合成模块 文本转TTS 真人发音 SYN6288