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

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

例:

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

这是参数列表的旧式语法,仍然受支持。 在K&R C中,你也可以不使用类型声明,而是默认为int。 即

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

将是相同的功能。


有趣的是,调用约定与功能的区别,以及没有原型的功能。 考虑一个旧式的定义:

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


这是来电者的K&R风格或旧式声明。

请注意,该声明与现代声明明显不同。 K&R声明不会为函数引入原型,这意味着它不会将参数的类型暴露给外部代码。

链接地址: http://www.djcxy.com/p/40231.html

上一篇: C function syntax, parameter types declared after parameter list

下一篇: What's the difference between 'int?' and 'int' in C#?