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

时间:2022-06-29 21:44:55

I'm relatively new to C. I've come across a form of function syntax I've never seen before, where the parameter types are defined after that parameter list. Can someone explain to me how it is different than the typical C function syntax?

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

Example:

例子:

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

6 个解决方案

#1


56  

That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e.

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

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

would be the same function.

是同一个函数。

#2


24  

What's also interesting is the calling convention difference of functions with, and functions without a prototype. Consider an old style definition:

同样有趣的是函数和没有原型的函数之间的约定俗成的区别。考虑一个旧的风格定义:

void f(a)
 float a; {
 /* ... */
}

In this case, the calling convention is that all arguments are promoted before being passed to the function. So if f receives a double but the parameter has type float (which is perfectly valid) the compiler has to emit code that converts the double to a float prior to executing the function's body.

在本例中,调用约定是在传递给函数之前提升所有参数。因此,如果f接收到一个double,但是参数具有float类型(这是完全有效的),那么编译器必须在执行函数的主体之前发出将double转换为float的代码。

If you include a prototype, the compiler does not do such automatic promotions anymore and any data passed is converted to the types of the parameters of the prototype as if by assignment. So the following is not legal and results in undefined behavior:

如果您包含了一个原型,编译器就不会再进行这样的自动升级了,并且传递的任何数据都将被转换为原型参数的类型,就像分配一样。因此,下列行为是不合法的,会导致不明确的行为:

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

}

In this case, the function's definition would convert the submitted parameter from double (the promoted form) to float because the definition is old-style. But the parameter was submitted as a float, because the function has a prototype. Your options of solving the contradictions are the two following:

在这种情况下,函数的定义将提交的参数从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) {

}

Option 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.

如果您有选择的余地,那么应该选择第二种方法,因为它可以预先摆脱旧的样式定义。如果一个函数的这种矛盾的函数类型出现在同一个翻译单元中,编译器通常会告诉您(但不是必需的)。如果这种矛盾出现在多个翻译单元上,那么错误很可能会被忽略,从而导致难以预测错误。最好避免这些旧的样式定义。

#3


10  

This is the so caller K&R style or old-style declaration.

这是so调用者K&R样式或旧式样式声明。

Note, that this declaration is significantly different from the modern declaration. K&R declaration does not introduce a prototype for the function, meaning that it doesn't expose the types of the parameters to the outside code.

注意,本宣言与《现代宣言》有很大不同。K&R声明没有为函数引入原型,这意味着它不向外部代码公开参数的类型。

#4


4  

While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes.
Without function prototypes the compiler will not check if the functions are called correctly.

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

#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;
}

When the program is run, the output on my machine is

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

$ 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

#5


3  

There is no difference, it is just that that is the old syntax for function declarations in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as another answer seems to suggest)

这没有区别,只是这是C语言中函数声明的旧语法——它使用的是pre - ANSI。不要写这样的代码,除非你打算把它给你80年代的朋友。而且,永远不要依赖于隐式类型假设(另一个答案似乎表明)

#6


1  

Its just the same but old fashion. You probably found it is some old, legacy code.

这是老一套。您可能发现它是一些旧的、遗留的代码。

#1


56  

That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e.

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

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

would be the same function.

是同一个函数。

#2


24  

What's also interesting is the calling convention difference of functions with, and functions without a prototype. Consider an old style definition:

同样有趣的是函数和没有原型的函数之间的约定俗成的区别。考虑一个旧的风格定义:

void f(a)
 float a; {
 /* ... */
}

In this case, the calling convention is that all arguments are promoted before being passed to the function. So if f receives a double but the parameter has type float (which is perfectly valid) the compiler has to emit code that converts the double to a float prior to executing the function's body.

在本例中,调用约定是在传递给函数之前提升所有参数。因此,如果f接收到一个double,但是参数具有float类型(这是完全有效的),那么编译器必须在执行函数的主体之前发出将double转换为float的代码。

If you include a prototype, the compiler does not do such automatic promotions anymore and any data passed is converted to the types of the parameters of the prototype as if by assignment. So the following is not legal and results in undefined behavior:

如果您包含了一个原型,编译器就不会再进行这样的自动升级了,并且传递的任何数据都将被转换为原型参数的类型,就像分配一样。因此,下列行为是不合法的,会导致不明确的行为:

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

}

In this case, the function's definition would convert the submitted parameter from double (the promoted form) to float because the definition is old-style. But the parameter was submitted as a float, because the function has a prototype. Your options of solving the contradictions are the two following:

在这种情况下,函数的定义将提交的参数从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) {

}

Option 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.

如果您有选择的余地,那么应该选择第二种方法,因为它可以预先摆脱旧的样式定义。如果一个函数的这种矛盾的函数类型出现在同一个翻译单元中,编译器通常会告诉您(但不是必需的)。如果这种矛盾出现在多个翻译单元上,那么错误很可能会被忽略,从而导致难以预测错误。最好避免这些旧的样式定义。

#3


10  

This is the so caller K&R style or old-style declaration.

这是so调用者K&R样式或旧式样式声明。

Note, that this declaration is significantly different from the modern declaration. K&R declaration does not introduce a prototype for the function, meaning that it doesn't expose the types of the parameters to the outside code.

注意,本宣言与《现代宣言》有很大不同。K&R声明没有为函数引入原型,这意味着它不向外部代码公开参数的类型。

#4


4  

While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes.
Without function prototypes the compiler will not check if the functions are called correctly.

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

#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;
}

When the program is run, the output on my machine is

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

$ 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

#5


3  

There is no difference, it is just that that is the old syntax for function declarations in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as another answer seems to suggest)

这没有区别,只是这是C语言中函数声明的旧语法——它使用的是pre - ANSI。不要写这样的代码,除非你打算把它给你80年代的朋友。而且,永远不要依赖于隐式类型假设(另一个答案似乎表明)

#6


1  

Its just the same but old fashion. You probably found it is some old, legacy code.

这是老一套。您可能发现它是一些旧的、遗留的代码。