函数声明与原型的替代(K&R)C语法

这个C语法有什么用处 – 使用'K&R'样式函数声明?

 int func (p, p2) void *p; int p2; { return 0; } 

我能够在Visual Studios 2010beta中编写这个

 //yes the params are flipped void f() { void *v=0; func(5,v); } 

我不明白。 这个语法有什么意义? 我可以写:

 int func (p, p2) int p2; { return 0; } //and write int func (p, p2) { return 0; } 

它似乎指定的唯一的事情是它使用了多less个参数和返回types。 我猜没有types的参数是有点酷,但为什么允许它和函数声明后的int paranName ? 有点奇怪。

也是这个标准的C吗?

你所问的问题实际上是两个问题,而不是一个问题。 到目前为止,大多数回复都试图用通用的方式来覆盖整个事物:“这是K&R风格”的答案,而实际上只有一小部分与所谓的K&R风格有关(除非你看到整个C语言作为“K&R式”以某种方式:)

第一部分是函数定义中使用的奇怪语法

 int func(p, p2) void *p; int p2; /* <- optional in C89/90, but not in C99 */ { return 0; } 

这个实际上是一个K&R风格的函数定义。 其他答案已经涵盖了这个很好。 实际上,这并没有多大的意义。 该语法已被废弃,但即使在C99中也是完全支持的(除了C99中的“无隐式int”规则,意味着在C99中不能省略p2的声明)。

第二部分与K&R风格无关。 我指的是可以用“交换”参数来调用函数的事实,即在这样的调用中不进行参数types检查。 这与K&R风格的定义本身几乎没有关系,但它与你的function没有任何原型有关。 当你声明一个像这样的函数时,你会看到C语言

 int foo(); 

它实际上声明了一个函数foo ,它带有未指定数量的未知types的参数 。 你可以称之为

 foo(2, 3); 

并作为

 j = foo(p, -3, "hello world"); 

等等(你明白了);

只有具有适当参数的调用才会“起作用”(也就是说其他调用会产生不确定的行为),但是完全取决于您是否确保其正确性。 编译器不需要诊断不正确的,即使它奇迹般地知道正确的参数types及其总数。

其实这个行为是C语言的一个特点 。 一个危险的,但是一个function。 它可以让你做这样的事情

 void foo(int i); void bar(char *a, double b); void baz(void); int main() { void (*fn[])() = { foo, bar, baz }; fn[0](5); fn[1]("abc", 1.0); fn[2](); } 

即混合不同的函数types在一个“多态”数组没有任何types转换(可变函数types不能在这里使用)。 再次,这种技术的内在危险是非常明显的(我不记得曾经使用它,但我可以想象它可以在哪里有用),但这毕竟是C。

最后,将答案的第二部分与第一部分联系起来。 当你创build一个K&R风格的函数定义时,它不会引入该函数的原型。 就functiontypes而言,你的func定义声明为func

 int func(); 

也就是说既没有声明types也没有声明参数的总数。 在你原来的文章中,你会说“…它似乎指定了它使用了多less个参数…”。 从forms上讲,它不是! 在你的双参数K&R风格的func定义之后,你仍然可以调用func

 func(1, 2, 3, 4, "Hi!"); 

而且不会有任何违反约束的情况。 (通常,一个质量编译器会给你一个警告)。

另外,一个有时被忽视的事实是

 int f() { return 0; } 

也是K&R风格的函数定义,不会引入原型。 为了使其成为“现代”,你必须在参数列表中加一个明确的void

 int f(void) { return 0; } 

最后,与普遍的看法相反,C99完全支持K&R风格的函数定义和非原型函数声明。 如果我没有记错的话,那么从C89 / 90开始,前者已经被弃用了。 C99要求函数在第一次使用之前被声明,但声明不一定是原型。 混淆显然源于stream行的术语混淆:许多人称任何函数声明为“原型”,而实际上“函数声明”与“原型”不同。

这是相当古老的K&R C语法(在ANSI / ISO C之前)。 现在,你不应该再使用它了(因为你已经注意到它的主要缺点:编译器不会检查你的参数types)。 在你的例子中,参数types实际上默认为int

当时,这个语法被使用,有时候会find类似的function

 foo(p, q) { return q + p; } 

这实际上是一个有效的定义,因为foopq的types默认为int

这只是一个古老的语法,它可能会让您更熟悉“ANSI C”语法。 通常称为“ K&R C ”。

编译器支持它是完整的,并能够处理旧的代码库,当然。

这是C在1989年被标准化之前的原始K&R语法。C89引入了从C ++借用的函数原型,并且弃用了K&R语法。 没有理由在新代码中使用它(以及大量的原因)。

当C没有function原型的时候,这是一个遗留问题。 那么,(我认为)函数被假定为返回int并且其所有参数被假定为int 。 没有检查function参数。

使用当前C语言中的函数原型要好得多。
必须在C99中使用它们(C89仍然接受旧的语法)。

而且C99需要声明函数(可能没有原型)。 如果你从头开始编写一个新的函数,你需要提供一个声明……把它作为一个原型:你什么都不会丢失,并从编译器中获得额外的检查。

这是一种旧式的函数声明。 请看这个链接。

https://stackoverflow.com/questions/22500/what-are-the-major-differences-between-ansi-c-and-kr-c 链接文本