函数声明与原型的替代(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; }
这实际上是一个有效的定义,因为foo
, p
和q
的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 链接文本