C函数语法,参数列表后声明的参数类型

Joh*_*ohn 76 c syntax function

我是C的新手.我遇到过一种我以前从未见过的函数语法形式,参数类型在参数列表之后定义.有人可以向我解释它与典型的C函数语法有何不同?

例:

int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
Run Code Online (Sandbox Code Playgroud)

Fer*_*cio 65

这是参数列表的旧式语法,仍然受支持.在K&R C中,您也可以省略类型声明,它们将默认为int.即

main(argc, argv)
char *argv[];
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

将是相同的功能.

  • C89/90和C99仍然正式支持K&R风格的声明.但是,在C99中,必须显式声明所有参数(不再是"隐式int"规则). (16认同)
  • @ChrisCirefice 4 年后回答你:在 C99 中,所有参数都必须在参数列表中声明。在函数中声明的变量从未默认为 `int`,因此必须显式声明。 (2认同)

Joh*_*itb 28

有趣的是函数的调用约定差异,以及没有原型的函数.考虑旧样式定义:

void f(a)
 float a; {
 /* ... */
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,调用约定是在传递给函数之前提升所有参数.因此,如果f接收到double但参数具有类型float(完全有效),则编译器必须发出代码,在执行函数体之前将double转换为float.

如果包含原型,则编译器不再执行此类自动提升,并且传递的任何数据都将转换为原型参数的类型,就像通过赋值一样.因此以下内容不合法,导致未定义的行为:

void f(float a);
void f(a)
  float a; {

}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,函数的定义会将提交的参数从double(提升的形式)转换为float因为定义是旧式的.但是参数是作为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) {

}
Run Code Online (Sandbox Code Playgroud)

如果你有选择,首选应该是首选,因为它预先摆脱了旧的样式定义.如果函数的这些矛盾函数类型出现在同一个转换单元中,编译器通常会告诉您(但不是必需的).如果在多个翻译单元上出现此类矛盾,则错误可能会被忽视,并且可能导致难以预测的错误.最好避免使用这些旧样式定义.


AnT*_*AnT 11

这是K&R风格旧式宣言.

请注意,此声明与现代声明明显不同.K&R声明没有为函数引入原型,这意味着它不会将参数类型公开给外部代码.


avi*_*ldg 5

没有区别,只是这是 C 中函数声明的旧语法——它是在 ANSI 之前使用的。除非您打算将其提供给 80 年代的朋友,否则切勿编写此类代码。此外,永远不要依赖于隐式类型假设(正如另一个答案似乎暗示的那样)

  • 咳咳……C99 仍然正式支持 K&R 样式声明,只有一个小改动——不再是“隐式 int”,所有参数都必须显式声明。 (2认同)

pmg*_*pmg 5

虽然函数定义的旧语法仍然有效(如果您询问编译器,则会出现警告),但使用它们并不提供函数原型。
\n如果没有函数原型,编译器将不会检查函数是否被正确调用。

\n\n
#include <stdio.h>\nint foo(c)\nint c;\n{ return printf("%d\\n", c); }\n\nint bar(x)\ndouble x;\n{ return printf("%f\\n", x); }\n\nint main(void)\n{\n    foo(42); /* ok */\n    bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

当程序运行时,我机器上的输出是

\n\n
$ gcc proto.c\n$ gcc -Wstrict-prototypes proto.c\nproto.c:4: warning: function declaration isn\xe2\x80\x99t a prototype\nproto.c:10: warning: function declaration isn\xe2\x80\x99t a prototype\n$ ./a.out\n42\n0.000000\n
Run Code Online (Sandbox Code Playgroud)\n