1.7 函数(Functions)
C中的函数等价于 Fortran 的子程序(subroutine)或函数,也等价于 Pascal 的过程(procedure)或函数。函数为计算的封装提供了一种简便的方法,此后用函数时不需考虑它如何实现。用设计正确的函数,程序员无需考虑功能是如何实现,而只需知道它有哪些功能。C中可简单、方便、高效地使用函数。经常看到在定义后仅调用一次的短函数,这可使代码段更清晰易读。
目前为止,使用的函数(printf、getchar、putchar)都是函数库提供的函数。现自编一些函数。 C没有像Fortran一样提供类于**的求幂运算符,现通过编写求幂函数power(m, n)来说明函数定义的方法。power(m, n)用于计算整数m的n次幂,n是正整数。函数调用power(2, 3)的结果为32。该函数并非实用的求幂函数,只能处理较小的整数的正整数次幂,但这对于说明问题已足够。(标准库中提供了一个计算x的y次幂函数pow(x, y)。)
下列是函数power(m, n)的定义及调用它的主程序,可看到完整的程序结构。
#include <stdio.h>
int power(int m, int n);
/* test power function */
main()
{
int i;
for (i = 0; i<10; ++i)
printf("%d %d %d\n", i, power(2,i),power(-3,i));
return 0;
}
/* power: raise base to n-th power; n >= 0 */
int power(int base, int n)
{
int i, p;
p = 1;
for(i = 1; i <= n; ++i)
p = p * base;
return p;
}
函数定义的一般形式:
返回值类型 函数名(0或多个参数声明)
{
声明部分
语句序列
}
函数定义可以以任意次序出现在一或多个源文件中,但同一函数不能分割存放在多个文件中。若源程序分散在多个文件中,那在编译和加载时就需要做更多工作,但这是操作系统的原因,并不是语言属性决定的。暂假定main和power两个函数放在同一文件中,那前面所学的有关运行C语言程序的知识仍有效。
main函数在下列语句中调用了两次power函数:
printf("%d %d %d\n", i, power(2, i), power(-i, 3));
每次调用时,main函数向power函数传递两个参数;在调用执行完成时,power函数向main函数返回一个格式化的整数并打印。在表达式中,power(2, i)同2和i一样是整数(并非所有函数的结果都是整型值,见第4章)。
power函数第1行
int power(int base, int n)
声明参数的类型、名字以及该函数返回结果的类型。power函数的参数使用的名字只在power函数内部有效,对其他任何函数都不可见:其他函数可用与之相同的参数名字而不引起冲突。变量i与p同样:power函数中的i与main函数中的i无关。
通常把函数定义中圆括号内列表中出现的变量称为形式参数,而把函数调用中与形式参数对应的值称为实际参数。
power 函数的结果通过return语句返回给main函数。关键字 return 后面可跟任何表达式,形式:
return 表达式;
函数不一定都有返回值;不带表达式的 return 语句将把控制权返回给调用者,但不返回有用的值。这等同于在到达函数的右终结画花括号时,函数就“到达了尽头”。主调函数(the calling fuction)也可以忽略函数返回的值。
注意,main函数的末尾有条return语句。main本身也是函数,它也可向其调用者返回一个值,该调用者实际是程序的执行环境。一般地,‘返回值为0’表示正常终止,‘返回值为非0’表示出现异常情况或出错结束条件。为简洁,前面的main函数都省略了return语句,但将在以后的main函数中包含return语句以提醒大家注意:程序还要向其执行环境返回状态。
出现在main函数之前的声明语句
int power(int m, int n) ;
表明power函数有两个int类型的参数,并返回一个int类型的值。这种声明称为函数原型,它必须与power函数的定义和用法一致。若函数的定义、用法与函数的原型不一致,将出错。
函数原型与声明中参数名不要求相同。事实上,函数原型中的参数名是可选的,上面的函数原型也可写成:
int power (int, int);
但,合适的参数名能起到很好的说明性作用,因此在函数原型中总指明参数名。
回顾,ANSI C 同较早版本C语言最大区别在于函数的声明与定义方式。按C的最初定义,power函数应写成:
/* power: raise base to n-th power;n>=0 */
/* (old-style version) */
power(base, n)
int base, n;
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
其中,参数名在圆括号内指定,参数类型在左花括号前声明。若未声明某个参数的类型,默认为int类型。函数体与ANSI C中形式相同。
在C语言的最初定义中,可在程序开头按以下形式声明power函数:
int power();
函数声明中不允许包含参数列表,这样编译器就无法在此时检查power函数调用的合法性。事实上, power函数默认将被假定返回int类型的值,因此整个函数的声明可全部忽略。
在ANSI C中定义的函数原型语法中,编译器可很容易检测出函数调用中参数数目和类型方面的错误。 ANSI C仍支持旧式的函数声明与定义,这样至少可有个过渡阶段。但强烈建议:使用新式编译器时,最好用新式的函数原型声明方式。
练习1-15 重编1.2节中温度转换程序,用函数实现温度转换计算。