我对C来说比较新。我遇到过一种我从未见过的函数语法形式,其中参数类型是在该参数列表之后定义的。有人能向我解释它与典型的C函数语法有何不同吗?C函数语法,在参数列表之后声明的参数类型
例子:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
我对C来说比较新。我遇到过一种我从未见过的函数语法形式,其中参数类型是在该参数列表之后定义的。有人能向我解释它与典型的C函数语法有何不同吗?C函数语法,在参数列表之后声明的参数类型
例子:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
这对参数列表,仍支持旧风格的语法。在K & R C中,你也可以忽略类型声明,它们将默认为int。即
main(argc, argv)
char *argv[];
{
return 0;
}
将是相同的功能。
没有什么区别,只是它是C语言中旧函数声明的语法 - 它在ANSI之前使用过。 千万不要写这样的代码,除非你打算把它从80年代的给你的朋友。此外,从不依赖于隐式类型假设(因为另一个答案似乎暗示)
它只是一样的,但旧时尚。您可能会发现它是一些旧的旧版代码。
尽管函数定义的旧语法仍然有效(如果您询问编译器时会发出警告),但使用它们不会提供函数原型。
没有函数原型,编译器不会检查函数是否被正确调用。
#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }
int bar(x)
double x;
{ return printf("%f\n", x); }
int main(void)
{
foo(42); /* ok */
bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
return 0;
}
当程序运行时,我的机器上输出
$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
这就是呼叫者ķ& [R风格或旧式声明。
注意,这个声明是显着不同于现代的声明。 K & R声明不会为该函数引入原型,这意味着它不会将参数的类型暴露给外部代码。
还有一个有趣的地方是调用约定与函数的区别,以及没有原型的函数。考虑老式风格的定义:
void f(a)
float a; {
/* ... */
}
在这种情况下,调用约定是,所有的参数都被传递给函数之前提升。因此,如果f
收到double
,但参数的类型为float
(这非常有效),编译器必须发出代码,在执行函数的主体之前将double转换为float。
如果包含原型,编译器不再执行此类自动升级,并且任何传递的数据都将转换为原型的参数类型,就像通过赋值一样。所以下面是不合法的,并导致未定义的行为:
void f(float a);
void f(a)
float a; {
}
在这种情况下,该函数的定义将从double
提交的参数(推广形式),因为定义是旧式转换为float
。但是该参数是以浮点形式提交的,因为该函数有一个原型。你化解矛盾的选项是以下两种:如果你有选择,因为它摆脱了旧的样式定义的前面
// option 1
void f(double a);
void f(a)
float a; {
}
// option 2
// this declaration can be put in a header, but is redundant in this case,
// since the definition exposes a prototype already if both appear in a
// translation unit prior to the call.
void f(float a);
void f(float a) {
}
选项2应该是首选。如果函数的这种矛盾函数类型出现在同一个翻译单元中,编译器通常会告诉您(但不是必需的)。如果这种矛盾出现在多个翻译单元上,错误可能会被忽视,并可能导致很难预测错误。最好避免这些旧式的定义。
C89/90和C99都仍然正式支持K&R风格声明。但是,在C99中,所有参数都必须显式声明(不再有“隐式int”规则)。 – AnT 2009-10-18 17:12:11
我讨厌晚会(比如4年后?),但是你的意思是说,在C99中,他们需要在参数列表中*或*在函数*中显式声明*?例如,默认的int规则 - 因为它们不再默认为int,那么它们的类型需要在使用之前在函数中声明**如果**类型未在参数列表中提供? – 2013-09-30 10:43:14
@ChrisCirefice 4年后回答你:在C99中,所有参数必须在参数列表中声明。在函数中声明的变量从来没有默认为'int',因此必须明确声明。 – 2017-08-14 11:40:24