在ANSI C标准之前,声明函数的方案有缺陷,因为只需要声明函数的类型,不用声明任何参数。下面我们来看一下旧式函数声明会导致什么问题。
int imin( );
//告知编译器imin()返回int类型的值(旧)//
然而以上函数并未给出imin( )函数的参数个数和类型。因此,如果调用imin( )时使用的函数个数不对或者类型不匹配,编译器根本不会察觉出来。
问题
下面一个示例程序用过去声明函数的方式声明了imax( )函数,并错误地适应了该函数。
/*misuse.c ——错误使用函数*/
#include <stdio.h>
int imax(); /*旧式函数声明*/
int main(void)
{
printf("The maximum of %d and %d is %d.\n",3,5,imax(3));
printf("The maximum of %d and %d is %d.\n",3,5,imax(3.0,5.0));
return 0;
}
int imax(n,m)
int n,m;
{
return (n>m?n:m);
}
尽管有些问题,但还是可以编译和运行,输出示例如下
The maximum of 3 and 5 is 1606416656.
The maximum of 3 and 5 is 3886
之所以输出错误的结果,是因为它们运行的程序没有使用函数原型。
到底是哪里出了问题?由于不同系统内部机制不同,下面我们以使用PC和VAX的情况解释。
主调函数把它的参数储存在被称为栈的临时储存区,被调函数从栈中读取这些参数。对于该例,这两个过程并未互相协调。主调函数根据函数调用中的实际参数决定传递的类型,而被调函数根据它的形式参数读取值。因此,函数调用imax(3)把一个整数放在栈中。当imax()函数开始执行时,它从栈中读取两个整数。而实际上栈中只存放了一个待读取的整数,所以读取的第2个值是当时恰好在栈中的其他值。
第2次使用imax()函数时,它传递的是float类型的值。这次把两个double类型的值放在栈中(回忆前文,当float类型被作为参数传递时会被升级为double类型)。在我们的系统中,两个double类型的值就是两个64位的值,所以128位的数据被放在栈中。当imax( )从栈中读取两个int类型的整数,其中较大的是3886。
解决方案
针对参数不匹配的问题,ANSI C标准要求在函数声明时还要声明变量的类型,也就是前面提到的,使用函数原型来声明函数的返回类型、参数的数量和每个参数的类型。
未标明imax( )函数有两个int类型的参数,可以使用下面两种函数原型来声明
int imax(int, int)
int imax ( int a,int b)
第1种形式使用以逗号分隔的类型列表,第2种形式在类型后面添加了变量名。
注意:这里的变量名是假名,不必与函数定义的形式参数名一致