猿问

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

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

这有什么用?C语法-使用‘K&R’风格的函数声明?

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

我在VisualStudio2010测试版上写了这篇文章

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

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

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

它似乎唯一指定的是它使用了多少参数和返回类型。我想没有类型的参数是很酷的,但是为什么允许它和int paranName在函数声明器之后?很奇怪。

这还是标准C吗?


白衣非少年
浏览 1094回答 3
3回答

牛魔王的故事

你提出的问题实际上是两个问题,而不是一个问题。到目前为止,大多数回复都试图用通用的毯子“这是K&R风格”来回答整个问题,而实际上只有一小部分与所谓的K&R风格有关(除非你以某种方式将整个C语言看作是“K&R风格”):第一部分是函数中使用的奇怪语法。定义int&nbsp;func(p,&nbsp;p2)void&nbsp;*p;int&nbsp;&nbsp;p2;&nbsp;/*&nbsp;<-&nbsp;optional&nbsp;in&nbsp;C89/90,&nbsp;but&nbsp;not&nbsp;in&nbsp;C99&nbsp;*/{ &nbsp;&nbsp;return&nbsp;0;}这是一个K&R型函数的定义。其他答案也很好地说明了这一点。其实也没什么大不了的。语法不受欢迎,但即使在C99中仍然完全支持(C99中的“无隐式int”规则除外),这意味着在C99中您不能省略p2).第二部分与K&R风格无关。我指的是可以用“交换”参数调用函数,即在这样的调用中不进行参数类型检查。这与K&R风格的定义本身没有什么关系,但它与您的功能没有原型有关。您看,在C中,当您声明这样的函数时int&nbsp;foo();它实际上声明了一个函数foo这需要未知类型的未指定数目的参数..你可以称之为foo(2,&nbsp;3);和ASj&nbsp;=&nbsp;foo(p,&nbsp;-3,&nbsp;"hello&nbsp;world");ANS等等(你有这个想法);只有带有适当参数的调用才能“工作”(这意味着其他调用会产生未定义的行为),但完全由您来确保其正确性。即使编译器以某种方式神奇地知道正确的参数类型及其总数,也不需要对不正确的参数进行诊断。实际上,这种行为是特征C语言。一个危险的,但仍然是一个特征。它允许你做这样的事情void&nbsp;foo(int&nbsp;i);void&nbsp;bar(char&nbsp;*a,&nbsp;double&nbsp;b);void&nbsp;baz(void);int&nbsp;main(){ &nbsp;&nbsp;void&nbsp;(*fn[])()&nbsp;=&nbsp;{&nbsp;foo,&nbsp;bar,&nbsp;baz&nbsp;}; &nbsp;&nbsp;fn[0](5); &nbsp;&nbsp;fn[1]("abc",&nbsp;1.0); &nbsp;&nbsp;fn[2]();}也就是说,在没有任何类型转换的“多态”数组中混合不同的函数类型(不过,在这里不能使用各种函数类型)。同样,这种技术的内在危险是显而易见的(我不记得曾经使用过它,但我可以想象它在哪里是有用的),但这毕竟是C。最后,将答案的第二部分与第一部分联系起来的位。当你做一个K&R风格的函数定义时,它不会为这个函数引入一个原型。就函数类型而言,func定义声明func如int&nbsp;func();也就是说,既不声明参数的类型,也不声明参数的总数。在您最初的帖子中,您会说“.它似乎指定了它使用了多少个参数.”。从形式上说,它不是!在你的双参数K&R风格之后func定义仍然可以调用func如func(1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;"Hi!");也不会有任何违反约束的地方。(通常,高质量的编译器会给您一个警告)。另外,一个有时被忽视的事实是int&nbsp;f(){ &nbsp;&nbsp;return&nbsp;0;}也是一个K&R风格的函数定义,不引入原型。要使它成为“现代”,你必须明确地指出void在参数列表中int&nbsp;f(void){ &nbsp;&nbsp;return&nbsp;0;}最后,与流行的观点相反,在C99中完全支持K&R风格的函数定义和非原型函数声明。如果我没记错的话,前者自C89/90以来就被否决了。C99要求在第一次使用之前声明函数,但声明不需要是原型。这种混淆显然源于流行的术语混淆:许多人称任何函数声明为“原型”,而实际上“函数声明”与“原型”并不相同。

慕工程0101907

这是相当古老的K&R C语法(早于ANSI/ISO C)。现在,您不应该再使用它了(因为您已经注意到它的主要缺点:编译器不会为您检查参数的类型)。参数类型实际上默认为int在你的例子中。在使用这个语法的时候,人们有时会发现这样的函数foo(p,&nbsp;q)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;q&nbsp;+&nbsp;p;}的类型,实际上是一个有效的定义。foo,&nbsp;p,和q默认为int.

海绵宝宝撒

这只是一个古老的语法,早于你可能更熟悉的“ANSI C”语法。这叫“K&R C“,典型的。当然,编译器支持它是完整的,并且能够处理旧的代码库。
随时随地看视频慕课网APP
我要回答