1.7 函数
在C中,函数等同于Fortan中的子例程或函数,以及Pascal中的过程或函数。函数提供了一个简单的方式来封装一些计算,它能直接使用而不用担心它的具体实现。用正确设计的函数,就有可能不用管一项工作是“如何”完成的;知道完成了“什么”就够了。C使函数的使用简单、方便且高效;你常会看到短函数被定义但仅被调用一次,只是因为这样能部分代码更清晰。
由于C没有Fortran中的幂算子**,让我们写个函数 power(m,n)来计算整数m的整数n次幂。即 power(2,5) = 32。(标准库中有power(x,y)计算x的y次幂)
#include <stdio.h>
int power(int m, int n);
/* 测试power函数 */
main()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3,i));
}
/* 计算base的n次方;n>=0 */
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
函数定义的格式如下:
返回类型 函数名( 参数声明,如果有的话 )
{
声明
语句
}
多个函数定义,可以按任何顺序,出现在一个或者多个源文件中,当然一个函数定义不能拆开到多个源文件中。如果源程序是由多个文件组成的,而不是单个文件,那么为了编译和加载,你就要多告诉系统一些东西,但这是属于操作系统的问题,而不是语言的属性。当前假定所有函数都在一个文件,你就不用去多学怎么编译/处理/运行多个源文件的情况了。
在 printf("%d %d %d\n", i, power(2,i), power(-3,i)); 中,main调用power两次,每次各传递了两个参数并各返回了1个整数,用于格式化输出。在表达式中, power(2, i)与 2, i一样,都是整数。(并非所有函数都返回整数,见第四章)
power函数的第一行 int power(int base, int n) 声明了参数类型和参数名,以及函数返回的结果。power中的参数名称是局部的,对其他函数不可见:其他的例程可使用同样的名字而不会冲突。这也适用于变量 i 和 p: power中的 i 和main中的 i 毫无关系。
我们通常把函数定义里括号内的变量叫做parameter,而把函数被调用时带的值叫做argument。有时也用“形参”(formal argument)和“实参”(actual argument)来区分。
power计算出来的值通过 return语句返回给main。任何表达式都可以跟在return后面:
return 表达式
函数并不一定要返回值,不带表达式的return语句不会把数值,而是把控制权返回给调用者,就和函数执行到最末尾的大括号时所做的一样。而且调用者函数也可以忽略被调用函数的返回值。
你也许会注意到main的结尾处有个return语句。由于main也是个函数,因此也能返回一个值给它的调用者,即程序执行的环境。通常,0表示正常终止,非0表示不正常或错误的终止状况。前面我们不给main写返回值是为了简化,现在开始都要写了,提醒你程序要给它们的执行环境返回状态。
main前面的声明 int power(int m, int n); 说的是 power是一个期望接收两个int参数并返回int的函数。这个声明,被称为“函数原型”,必须和power的定义一致。若函数定义与原型不一致,或任何对函数的调用与原型不一致,则会出错。
参数名可以不用一致。实际上,参数名在函数原型中是可选的,所以能写为 int power(int, int); 但好的参数名更利于代码阅读,所以我们都会写参数名。
关于历史的说明:ANSI C 和早期版本的最大区别在于函数的定义和声明方式,原始版本C的power函数这样写:
/* 计算base的n次方;n>=0 */
/* 旧风格版本 */
int power(base, n)
int base, n;
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
参数名称放在括号内,而类型在左大括号之前声明;未声明的参数类型被当作int。(函数主体不变)
而程序开头的函数声明会是这样: int power(); 不允许加入参数列表,所以编译器不能事先检查power是否正确调用。实际上,默认power会被认为返回int,这整个声明都能去掉。
新的函数原型语法使编译器更容易检测到参数数量或类型的错误,旧风格的声明和定义在ANSI C中也是能用的,至少在过渡阶段,我们强烈建议只要你的编译器支持,就使用新风格。