K& R函数声明和ANSI函数声明之间有什么区别?
答案 0 :(得分:56)
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;
}
答案 1 :(得分:22)
旧版K& R-Style声明/定义
当Kernighan和Ritchie首次发表“The C Programming Language”时,C还没有提供全功能原型。存在函数的前向声明,但唯一的目的是指示返回类型。对于返回int
的函数,在C99之前不需要它们。
通过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;
}
意外K& R宣言
值得注意的是,C的新手在打算使用完整原型时可能会意外地使用K& R声明,因为他们可能没有意识到必须将空参数列表指定为void
。
如果您将函数声明并定义为
// 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;
}
...那么你实际上没有为没有参数的函数提供原型,而是为K& R-style声明了一个接受未知数量的未知类型参数的函数。
AnT在this answer中注意到一个类似的问题,即该语法已被弃用但从C99开始仍然合法(并且指向未知数量和参数类型的函数的函数指针仍具有潜在的应用程序,但风险很高未定义的行为);因此,如果在没有适当原型的情况下声明或调用函数,兼容编译器最多会产生警告。
调用没有原型的函数不太安全,因为编译器无法验证您是否以正确的顺序传递了正确数量和类型的参数;如果调用实际上不正确,则会产生未定义的行为。
声明和定义无参数函数的正确方法当然是:
// 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;
}
答案 2 :(得分:0)
我只是想在传统的K&用于返回int
值的函数的R样式类型修饰符甚至不是必需的。
考虑一个简单的HelloWorld程序的现代C11表示法:
int main(int argc, char **argv) {
printf("hello world\n");
return 0;
}
这相当于K& R符号样式:
main(argc, argv)
int argc;
char **argv;
{
printf("hello world\n");
return 0;
}
请注意int
之前的main()
会被忽略,但代码仍会编译。这是K& K的一部分R定义。
引用维基百科:
在C的早期版本中,如果在函数定义之前使用,则只需要声明返回非int值的函数;假设使用了没有任何先前声明的函数,如果使用了它的值,则返回int类型。
- 来源:https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
这可以说是传统的编码风格,应该避免由于清晰度问题,但很多时候旧算法教科书都喜欢这种类型的K& R风格。