为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C
幕布斯6054654 2019-07-06 17:42:36
函数语法,参数列表后声明的参数类型我对C比较陌生。我遇到了一种以前从未见过的函数语法,在参数列表之后定义了参数类型。有人能向我解释一下它与典型的C函数语法有何不同吗?例子:int main (argc, argv)int argc;char *argv[];{return(0);}
查看完整描述

3 回答

?
潇湘沐

TA贡献1816条经验 获得超6个赞

这是参数列表的旧式语法,它仍然被支持。在K&R C中,您还可以关闭类型声明,它们将默认为int。E.

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

同样的功能。


查看完整回答
反对 回复 2019-07-06
?
慕尼黑8549860

TA贡献1818条经验 获得超11个赞

同样有趣的是函数调用约定的差异,以及没有原型的函数。考虑一下旧的风格定义:

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,因为它可以预先消除旧的样式定义。如果函数的这种矛盾函数类型出现在同一个转换单元中,编译器通常会告诉您(但不是必需的)。如果这样的矛盾出现在多个翻译单位,错误可能会被忽视,并可能导致很难预测错误。最好避免使用这些旧的样式定义。


查看完整回答
反对 回复 2019-07-06
?
婷婷同学_

TA贡献1844条经验 获得超8个赞

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

#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


查看完整回答
反对 回复 2019-07-06
  • 3 回答
  • 0 关注
  • 487 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信