首页 理论教育C语言程序设计参数传递规则

C语言程序设计参数传递规则

【摘要】:我们通过下面的示例来说明按值传递方式中参数在函数之间的传递。图5.1实参与形参传递示意图当数组名作为函数参数时,函数传递数据方式采用的是“按地址传递”的方式,但要求形参和相对应的实参都必须是类型相同的数组。图5.3数组v的存储形式这样一来,形参数组中元素值的改变就会反过来影响到实参数组。

大多数情况下,在调用函数时,主调函数和被调函数之间有数据的传递关系。在5.1.2节中已经提到了形式参数和实际参数的概念:在定义函数时函数名后面的参数称为“形式参数”(简称“形参”),在主调函数中调用一个函数时,函数名后面的参数(可以为一个表达式)称为“实际参数”(简称“实参”)。C语言提供了两种参数传递方式:按值传递和按地址传递。

1.按值传递

按值传递:调用时,主调函数把实参的值传给被调函数的形参,形参的变化不会改变实参的值,这是一种单向的数据传递方式。

当实参是变量名、常数、表达式或数组元素,而形式参数是变量时,参数传递方式采用的是“按值传递”的方式。我们通过下面的示例来说明按值传递方式中参数在函数之间的传递。

例5.2 给出函数power(m,n)的定义及调用它的主程序(power(m,n)函数用于计算整数m的正整数次幂n,如power(2,5)的值为32)。

#include<stdio.h>

说明:

例5.2中,main()函数在printf语句中两次调用了函数power():

printf("%d%d%d\n",i,power(x,i),power(y,i));

我们以第一次调用(即power(x,i))为例,在第一次调用中,x和i分别复制了一份值传递给被调函数power()的形参m和n,然后在被调函数中进行数据的处理,最后把计算的结果传回给调用它的main函数中的printf()函数。

说明:

(1)定义函数时,定义的形参并不占用实际的存储单元,只有在被调用时系统才给它分配存储单元,在调用结束后,形参所占用的存储单元被释放。

(2)实参的个数与类型应与形参一致,否则将会出现编译错误。

(3)C语言规定,函数间的参数传递是“按值传递”(即单向传递)时,实参可以把值传给形参,但形参的值不能传给实参,也就是说对形参的修改不会影响对应的实参。这是由于在内存中,实参与形参是不同的存储单元,如图5.1所示。

2.按地址传递

按地址传递:函数调用时,主调函数把实参的地址传给被调函数的形参。由于传递的是地址,使得形参与实参共享同一存储单元中的数据,这样通过形参可以直接引用或处理该地址中的数据。(www.chuimin.cn)

图5.1 实参与形参传递示意图

当数组名作为函数参数时,函数传递数据方式采用的是“按地址传递”的方式,但要求形参和相对应的实参都必须是类型相同的数组。我们通过下面的例子来说明按地址传递方式中参数在函数之间的传递。

例5.3 顺序查找。顺序查找是把给定的值与这组数据中的每个值顺序比较。如果找到,就输出这个值的位置;如果找不到则返回一个查找失败的信息。下面是顺序查找的程序。

本程序中使用了一个数组名作为参数。函数seq_search()中形参v没有指定数组的长度,要处理的元素的个数由其后所跟的参数n决定,当然也可以把形参v声明为

int v[SIZE];

但这样在实际应用中并不方便,它使函数seq_search()依赖于具体问题,失去了通用性,所以最好是按程序中那样来写。

C语言中规定,一个数组名代表存放那个数组的内存首地址,所以它实际上是一个地址值。那么传递一个地址值对程序会造成什么影响呢?假定数组d的首地址是2000,则数组d的各元素值顺序地存放在从2000开始的存储单元中,如图5.2所示。

图5.2 数组d的存储形式

当函数seq_search被调用时,将实参d的首地址传给形参v,于是数组v的首地址也变为2000,各元素放置在以2000开始的地址空间中,这样两个数组就共占一段内存单元。如图5.3所示。

图5.3 数组v的存储形式

这样一来,形参数组中元素值的改变就会反过来影响到实参数组。这一点与变量做函数参数的情况是完全不一样的。我们在程序设计的过程中可以利用这个特点来改变实参数组元素的值(如数组的排序)。