6.4 步骤3:函数的调用

通过具体的参量使函数完成一个具体的任务叫做函数的调用(Function-call)。函数调用可以发生在任何函数体内,可以调用其他函数也可以调用自身。

本程序计算(2+3)×4的任务是在main()函数中提出的要求,因此在main()函数内调用qiuji()函数。具体的做法是:

6.4 步骤3:函数的调用 - 图1

写在()里的2+3和4是计算乘积所需要的具体数据,叫做实参(Actual Argument)。实参必须是一个有值的表达式,各个实参之间用“,”分隔。

qiuji(2+3, 4)的含义是函数名qiuji与表达式“2+3”及表达式“4”共同进行“()”运算,这个运算叫函数调用运算,也属于后缀运算一类,优先级16,结合性从左到右。函数调用的本质是一种运算,所以函数调用也被称为“函数调用表达式”。这个表达式有一个值(无值可以看成是有一个void类型的值),这个值可能被使用也可能被忽略(10),也就是说进行函数调用可能是为了求值,也可能仅仅是为了利用函数的副效应。

函数调用这种运算的规则描述比较复杂,具体步骤如下。

(1)首先计算出各个实参的值(本例中两个实参的值分别为5和4)。

(2)把计算出的各个实参的值依次作为对应形参的初值(即zsl和zs2的初值分别为5和4)。

(3)执行被调用函数的函数体部分。

(4)遇见return语句返回到调用函数处。

(5)既然在函数调用时“()”是一个运算符,那么qiuji(2+3,4)就是一个表达式,这个表达式的值的类型就是函数qiuji()返回值的类型,这个表达式的值就是相应return语句返回的表达式的值。如果函数的类型是void类型,那么相应的函数调用表达式就是void类型,也就是没有值(晦涩而高雅的说法是值是一个空集)。

qiuji(2+3,4)这个int类型的表达式,可以出现在代码中任何允许int类型表达式出现的地方,因此可以通过调用printf()函数把这个表达式的值输出到标准输出设备(显示器)。

而对printf()函数的调用,同样应该在调用之前写上这个函数的原型。由于文本文件stdio.h中有printf()函数的函数原型,所以可以通过在源程序代码的开头写预处理命令#include<stdio.h>达到这个目的。

这样最后的源程序的代码就是:

6.4 步骤3:函数的调用 - 图2

6.4 步骤3:函数的调用 - 图3

需要重申的是,实参只要是一个与形参类型相符合的表达式就可以参与函数调用运算,前面代码中2+3和4是以int类型的表达式作为实参参与调用qiuji()函数的,代码中的qiuji(2*3,4)是以一个int类型的表达式作为printf()函数的实参的。

程序中没有printf()函数、system()函数的定义,这两个函数是编译器提供的,它们在你编程之前就已经定义完毕甚至已经编译完毕了,因此使用时只要写出函数原型(通常通过#include预处理命令实现)即可直接进行函数调用。

编译器提供的函数叫做库函数(11),这些函数都是已经定义、编译完毕并以库文件的形式随编译器一起提供给编程者的。它们在安装好编译器软件之后也同时被复制存放在机器的硬盘中。C标准规定了编译器至少应该提供哪些库函数,这些库函数叫做标准库函数。一般编译器提供的库函数比标准库函数要多些,具体要查阅相关的使用手册。

也可以自己生成静态库函数或者使用第三方(你和编译器作者之外的人)的静态库函数库。限于篇幅,具体的步骤在此就不详述了。

练习

写一程序,通过函数调用求

1+2+……100+3+9+15+……+(3+20×6)的值(注:这是两个等差数列)。