支持这种记法的原因是历史原因。在第一个C标准(C89/C90)之前,无法在C中使用原型;原型是标准C最重要的特性之一。因此,所有函数声明都是以“空括号”样式编写的(如果它们真的被编写了的话;大多数返回
int
的函数根本没有声明)。类型
void
也在C89/C90中添加,尽管一些编译器在标准确定之前就支持它了。
由于对于C89/C90的成功来说,现有代码的大部分仍然需要继续工作,所以标准必须允许使用空括号样式。因此,您的代码可能是以预标准C的形式编写的:
#include <stdio.h>
int fun();
int main(void)
{
fun(12, 13.22, 1234567, "wow", 'c');
return 0;
}
fun(i, d, l, s, c)
long l;
char c;
char *s;
double d;
{
printf("This is what happened to those arguments:\n");
printf("i = %d\n", i);
printf("d = %f\n", d);
printf("l = %ld\n", l);
printf("s = [%s]\n", s);
printf("c = %c\n", c);
}
有兴趣的话:您可以在函数定义中省略char *s;
这一行,然后仍然编译并产生相同的输出。然而,这样做是个不好的主意。您可以将int fun();
这一行替换为static fun();
,当没有请求诊断时,代码将编译得很干净。
即使现在使用GCC 9.3.0编译此文件(old31.c
),也不会收到任何警告:
$ gcc -std=c90 -o old31 old31.c
$
您提供的示例代码违背了向后兼容性规定。使用
void
表示它是新代码(在许多预先标准化的C编译器中,它将是无效的,因为它使用了
void
)。新代码不应该没有充分理由就利用向后兼容性规定。这在1991年和当前千年都是正确的(但在1991年,有更多的充分理由来利用向后兼容性规定)。良好的预标准代码通常按照它们使用的顺序列出所有参数。省略的定义和顺序不正确的定义并不完全令人满意。
你问:
在问题的代码中,这些参数无法被使用。调用者将值推送到堆栈上,并在函数返回时将它们弹出。调用的函数不知道它们的存在,也不能对它们进行任何操作。
不可能--没有任何标准机制可以做到这一点。