14-ANSI的解决方案
9.2.2 ANSI的解决方案
针对参数不匹配的问题,ANSI C标准要求在函数声明时还要声明变量的类型,即使用函数原型(function prototype)来声明函数的返回类型、参数的数量和每个参数的类型。未标明 imax() 函数有两个 int 类型的参数,可以使用下面两种函数原型来声明:
int imax(int, int);
int imax(int a, int b);
第1种形式使用以逗号分隔的类型列表,第2种形式在类型后面添加了变量名。注意,这里的变量名是假名,不必与函数定义的形式参数名一致。
有了这些信息,编译器可以检查函数调用是否与函数原型匹配。参数的数量是否正确?参数的类型是否匹配?以 imax() 为例,如果两个参数都是数字,但是类型不匹配,编译器会把实际参数的类型转换成形式参数的类型。例如, imax(3.0, 5.0) 会被转换成 imax(3, 5) 。我们用函数原型替换程序清单9.4中的函数声明,如程序清单9.5所示。
程序清单9.5 proto.c 程序
/* proto.c -- 使用函数原型 */
#include <stdio.h>
int imax(int, int); /* 函数原型 */
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(int n, int m)
{
return (n > m ? n : m);
}
编译程序清单9.5时,我们的编译器给出调用的 imax() 函数参数太少的错误消息。
如果是类型不匹配会怎样?为探索这个问题,我们用 imax(3, 5) 替换 imax(3) ,然后再次编译该程序。这次编译器没有给出任何错误信息,程序的输出如下:
The maximum of 3 and 5 is 5.
The maximum of 3 and 5 is 5.
如上文所述,第2次调用中的 3.0 和 5.0 被转换成 3 和 5 ,以便函数能正确地处理输入。
虽然没有错误消息,但是我们的编译器还是给出了警告: double 转换成 int 可能会导致丢失数据。例如,下面的函数调用:
imax(3.9, 5.4)
相当于 :
imax(3, 5)
错误和警告的区别是:错误导致无法编译,而警告仍然允许编译。一些编译器在进行类似的类型转换时不会通知用户,因为C标准中对此未作要求。不过,许多编译器都允许用户选择警告级别来控制编译器在描述警告时的详细程度。