int f(void);
将f 声明为不带参数并返回int 结果的函数,而
int f();
将f 声明为采用固定但未指定数量和类型的参数的函数(当然,返回int 结果)。
鉴于这样的声明,必须有一个定义在某处实际定义参数。如果不带参数,可能定义为:
int f() {
return 42;
};
如果它需要2个int参数,它可能被定义为:
int f(int x, int y) {
return x + y;
}
任一定义与int f();兼容,但只有第一个与int f(void)兼容。
一个指定参数类型的函数声明,或者,作为一种特殊情况,使用void 关键字来指定没有参数,是一个原型。 不执行此操作的函数声明,例如int f(); 是旧式声明。
除非您使用不支持原型的具有数十年历史的 pre-ANSI 编译器,或者您正在维护非常旧的代码并且没有时间或其他资源来更新它,否则 没有理由不使用原型。如果你调用一个没有可见原型的函数,你仍然需要传递正确数量和类型的参数;不同的是,如果调用不正确,编译器将无法告诉你。
(您可以定义一个接受可变数量和类型参数的函数;printf 就是一个例子。这是使用, ... 表示法完成的。函数本身使用<stdarg.h> 中定义的特性来处理论点。但这与您问题中显示的声明无关。)
这是一个使用过时的旧式函数声明和定义的小程序:
#include <stdio.h>
#include <stdlib.h>
int add();
int main(argc, argv)
int argc;
char **argv;
{
if (argc == 3) {
/* NOTE: atoi() does no error checking */
printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
}
else {
fprintf(stderr, "Usage: %s x y\n", argv[0]);
exit(EXIT_FAILURE);
}
}
int add(x, y)
int x, y;
{
return x + y;
}
请注意,如果我写了add(1, 2, 3, 4) 或add("foo", "bar"),编译器就不会发现错误;该程序只是行为不端。
这是一个使用现代函数声明和定义的等效程序:
#include <stdio.h>
#include <stdlib.h>
int add(int x, int y);
int main(int argc, char **argv) {
if (argc == 3) {
/* NOTE: atoi() does no error checking */
printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
}
else {
fprintf(stderr, "Usage: %s x y\n", argv[0]);
exit(EXIT_FAILURE);
}
}
int add(int x, int y) {
return x + y;
}
可见的原型意味着编译器能够诊断不正确的调用。