7.4.2 数组名作为函数实参

在讲解函数调用形式时曾说过:实参和形参个数要相等,类型要一致,按顺序对应,一一传递。C语言规定,实参变量对形参变量的数据传递是“值传递”,也就是单向传递,只由实参传递给形参,不能由形参传递给实参。

前面已经看过了用变量作为函数的实参(这是将变量进行值传递),此外,数组名也可以作为函数实参,数组名代表的是数组的首地址,所以,将数组名作为函数的实参进行传递时,传递的其实是数组的首地址。此时,函数中的形参也应该用数组名(或数组指针,指针后续会讲解)。

值得强调的是:将数组名作为函数参数时,就不是“值传递”的概念了,不再是单向传递,而是把实参数组的开始地址(首地址)传递给了形参,这就相当于实参和形参指向(代表)了同一段内存单元,这其实叫地址传递。也就是说,形参数组中各个元素的值如果发生了改变,就等价于实参数组中元素的值发生了相应的改变。这一点是与普通变量作为函数参数明显不同的地方。看看如下范例,有5个学生,考试成绩保存在一个数组中,调用一个函数,用来修改其中2个学生的考试成绩:

在上面的范例中,调用changevalue函数之前,数组元素看起来如图7.8所示。

而在进入changevalue函数中后,在形参接收了实参传递进来的数组首地址后,数组元素看起来如图7.9所示。

图7.8 调用changevalue函数前实参a数组元素内存布局示意

图7.9 调用changevalue函数时形参ba数组元素内存布局示意

有几点说明:

(1)如果实参为数组名,则形参也应该为数组名,也就是说,形参也应该被定义为一个数组。

(2)实参数组与形参数组类型必须一致,例如都为int型,否则,结果会出错或者出现意想不到的事情。

(3)形参数组大小可以不指定,即便指定了也可以与实参数组大小不一致,因为C编译器对形参数组大小不做检查,只是将实参数组的首地址传递给形参数组,甚至可以定义形参数组大小比实参数组大,但超过实参数组大小的部分内存不要去引用,否则会导致程序立即或者不定时崩溃。例如,如果像下面这样定义changevalue函数(形参中指定了数组大小并且比实参中的数组大小要大),如图7.10所示,千万不要去引用ba[5]~ba[8]甚至更大下标的元素:

图7.10 调用changevalue函数时ba数组元素能引用的只有ba[0]~ba[4]