猿问

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

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

我对C比较陌生。我遇到了一种以前从未见过的函数语法,在参数列表之后定义了参数类型。有人能向我解释一下它与典型的C函数语法有何不同吗?

例子:

int main (argc, argv)int argc;char *argv[];{return(0);}


幕布斯6054654
浏览 488回答 3
3回答

潇湘沐

这是参数列表的旧式语法,它仍然被支持。在K&R C中,您还可以关闭类型声明,它们将默认为int。E.main(argc, argv)char *argv[];{     return 0;}同样的功能。

慕尼黑8549860

同样有趣的是函数调用约定的差异,以及没有原型的函数。考虑一下旧的风格定义:void f(a)  float a; {  /* ... */}在这种情况下,调用约定是在传递给函数之前提升所有参数。所以如果f接收double但是参数有类型float(这是完全有效的)编译器必须发出代码,在执行函数的主体之前将Double转换为Float。如果您包含一个原型,编译器将不再进行这种自动提升,传递的任何数据都会转换为原型参数的类型,就像通过赋值一样。因此,以下行为是不合法的,会导致未定义的行为:void f(float a);void f(a)   float a; {}在这种情况下,函数的定义将提交的参数转换为double(晋升表格)float因为定义是旧的。但该参数是作为浮点数提交的,因为该函数有一个原型。你们解决矛盾的办法有以下两种:// option 1void 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,因为它可以预先消除旧的样式定义。如果函数的这种矛盾函数类型出现在同一个转换单元中,编译器通常会告诉您(但不是必需的)。如果这样的矛盾出现在多个翻译单位,错误可能会被忽视,并可能导致很难预测错误。最好避免使用这些旧的样式定义。

婷婷同学_

虽然函数定义的旧语法仍然有效(如果您问编译器,有警告),但使用它们并不提供函数原型。如果没有函数原型,编译器将不会检查函数是否被正确调用。#include&nbsp;<stdio.h>int&nbsp;foo(c)int&nbsp;c;{&nbsp;return&nbsp;printf("%d\n",&nbsp;c);&nbsp;}int&nbsp;bar(x)double&nbsp;x;{&nbsp;return&nbsp;printf("%f\n",&nbsp;x);&nbsp;}int&nbsp;main(void){ &nbsp;&nbsp;&nbsp;&nbsp;foo(42);&nbsp;/*&nbsp;ok&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;bar(42);&nbsp;/*&nbsp;oops&nbsp;...&nbsp;42&nbsp;here&nbsp;is&nbsp;an&nbsp;`int`,&nbsp;but&nbsp;`bar()`&nbsp;"expects"&nbsp;a&nbsp;`double`&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;}当程序运行时,我的机器上的输出是$&nbsp;gcc&nbsp;proto.c $&nbsp;gcc&nbsp;-Wstrict-prototypes&nbsp;proto.c proto.c:4:&nbsp;warning:&nbsp;function&nbsp;declaration&nbsp;isn’t&nbsp;a&nbsp;prototype proto.c:10:&nbsp;warning:&nbsp;function&nbsp;declaration&nbsp;isn’t&nbsp;a&nbsp;prototype $&nbsp;./a.out 42 0.000000
随时随地看视频慕课网APP
我要回答