C语言 函数声明:K&R 与 ANSI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3092006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:43:01  来源:igfitidea点击:

Function declaration: K&R vs ANSI

ckr-c

提问by ashna

What are the differences between a K&R function declaration and an ANSI function declaration?

K&R 函数声明和 ANSI 函数声明之间有什么区别?

回答by Wizard

K&R syntax is obsolete, you can skip it unless you have to maintain very old code.

K&R 语法已过时,您可以跳过它,除非您必须维护非常旧的代码。

// K&R syntax
int foo(a, p) 
    int a; 
    char *p; 
{ 
    return 0; 
}

// ANSI syntax
int foo(int a, char *p) 
{ 
    return 0; 
}

回答by Theodore Murdock

Legacy K&R-Style Declarations/Definitions

传统 K&R 风格的声明/定义

When Kernighan and Ritchie first published "The C Programming Language", C didn't yet offer full function prototypes. Forward declarations of functions existed, but with the sole purpose of indicating a return type. For functions that returned int, they weren't required until C99.

当 Kernighan 和 Ritchie 首次发表“The C Programming Language”时,C 还没有提供完整的函数原型。存在函数的前向声明,但其唯一目的是指示返回类型。对于返回 的函数,int直到 C99 才需要它们。

By C89, the notion of a function prototype, which also specifies the types of the parameters (and, implicitly, their number) had been added. Since a prototype is also a type of function declaration, the unofficial term "K&R function declaration" is sometimes used for a function declaration that is not also a prototype.

到 C89,添加了函数原型的概念,它也指定了参数的类型(以及隐式地,它们的编号)。由于原型也是一种函数声明,非正式术语“K&R 函数声明”有时用于表示不是原型的函数声明。

// K&R declarations, we don't know whether these functions have parameters.
int foo(); // this declaration not strictly necessary until C99, because it returns int
float bar();

// Full prototypes, specifying the number and types of parameters
int foo(int);
float bar(int, float);

// K&R definition of a function
int foo(a)
    int a; // parameter types were declared separately
{
    // ...
    return 0;
}

// Modern definition of a function
float bar(int a, float b) 
{
    // ...
    return 0.0;
}

The Accidental K&R Declaration

意外 K&R 声明

It's worth noting that newcomers to C may accidentally use K&R declarations when they intend to use a full prototype, because they may not realize that an empty parameter list must be specified as void.

值得注意的是,C 的新手在打算使用完整原型时可能会不小心使用 K&R 声明,因为他们可能没有意识到必须将空参数列表指定为void.

If you declare and define a function as

如果您将函数声明并定义为

// Accidental K&R declaration
int baz(); // May be called with any possible set of parameters

// Definition
int baz() // No actual parameters means undefined behavior if called with parameters.
          // Missing "void" in the parameter list of a definition is undesirable but not
          // strictly an error, no parameters in a definition does mean no parameters;
          // still, it's better to be in the habit of consistently using "void" for empty
          // parameter lists in C, so we don't forget when writing prototypes.
{
    // ...
    return 0;
}

...then you have not actually given a prototype for a function that takes no parameters, but a declaration in K&R-style for a function that accepts an unknown number of parameters of unknown type.

...那么您实际上并没有为不带参数的函数提供原型,而是为接受未知数量的未知类型参数的函数提供了 K&R 风格的声明。

AnT notes in this answerto a similar question that this syntax is deprecated but still legal as of C99 (and that function pointers to functions with unknown number and type of parameters still have potential applications, though at high risk of undefined behavior); as such, compliant compilers will, at best, produce a warning if a function is declared or called without a proper prototype.

AnT 在这个对类似问题的回答中指出,这种语法已被弃用,但从 C99 开始仍然合法(并且指向具有未知数量和参数类型的函数的函数指针仍然具有潜在应用,尽管存在未定义行为的高风险);因此,如果在没有适当原型的情况下声明或调用函数,兼容编译器最多只会产生警告。

Calling functions without prototypes is less safe, because the compiler cannot verify that you have passed the correct number and types of parameters in the correct order; undefined behavior results if the call is not actually correct.

调用没有原型的函数不太安全,因为编译器无法验证您是否以正确的顺序传递了正确数量和类型的参数;如果调用实际上不正确,则会导致未定义的行为。

The correct way to declare and define a parameterless function is, of course:

声明和定义无参数函数的正确方法当然是:

// Modern declaration of a parameterless function.
int qux(void);  // "void" as a parameter type means there are no parameters.
                // Without using "void", this would be a K&R declaration.

// Modern definition of a parameterless function
int qux(void)
{
    // ...
    return 0;
}

回答by BearAqua

I just want to add that in the traditional K & R style type modifiers for functions that return an intvalue aren't even necessary.

我只想在传统的 K & R 样式类型修饰符中添加它,int甚至不需要返回值的函数。

Consider the modern C11 notation of a simple HelloWorld program:

考虑一个简单的 HelloWorld 程序的现代 C11 符号:

int main(int argc, char **argv) {
    printf("hello world\n");
    return 0;
}

This is equivalent to the K & R notation style:

这等效于 K & R 符号样式:

main(argc, argv)
int argc;
char **argv;
{
 printf("hello world\n");
 return 0;
}

Note that the intbefore main()is ignored, but the code still compiles. That's a part of the K & R definition.

请注意,intbeforemain()被忽略,但代码仍然可以编译。这是 K & R 定义的一部分。

Quote Wikipedia:

引用维基百科:

In early versions of C, only functions that returned a non-int value needed to be declared if used before the function definition; a function used without any previous declaration was assumed to return type int, if its value was used.

在 C 的早期版本中,如果在函数定义之前使用,则只需要声明返回非 int 值的函数;如果使用了它的值,则假定在没有任何先前声明的情况下使用的函数返回类型 int。

--source: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C

--source: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C

This is arguably a legacy coding-style and should be avoided due to clarity issues, but quite often old algorithm textbooks favour this sort of K & R style.

这可以说是一种遗留的编码风格,由于清晰度问题应该避免,但是旧的算法教科书通常更喜欢这种 K&R 风格。