为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C
白衣非少年 2019-06-15 13:40:05
函数声明与原型的替代(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吗?
查看完整描述

3 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

你提出的问题实际上是两个问题,而不是一个问题。到目前为止,大多数回复都试图用通用的毯子“这是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风格无关。我指的是可以用“交换”参数调用函数,即在这样的调用中不进行参数类型检查。这与K&R风格的定义本身没有什么关系,但它与您的功能没有原型有关。您看,在C中,当您声明这样的函数时

int foo();

它实际上声明了一个函数foo这需要未知类型的未指定数目的参数..你可以称之为

foo(2, 3);

和AS

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

ANS等等(你有这个想法);

只有带有适当参数的调用才能“工作”(这意味着其他调用会产生未定义的行为),但完全由您来确保其正确性。即使编译器以某种方式神奇地知道正确的参数类型及其总数,也不需要对不正确的参数进行诊断。

实际上,这种行为是特征C语言。一个危险的,但仍然是一个特征。它允许你做这样的事情

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]();}

也就是说,在没有任何类型转换的“多态”数组中混合不同的函数类型(不过,在这里不能使用各种函数类型)。同样,这种技术的内在危险是显而易见的(我不记得曾经使用过它,但我可以想象它在哪里是有用的),但这毕竟是C。

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

int func();

也就是说,既不声明参数的类型,也不声明参数的总数。在您最初的帖子中,您会说“.它似乎指定了它使用了多少个参数.”。从形式上说,它不是!在你的双参数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要求在第一次使用之前声明函数,但声明不需要是原型。这种混淆显然源于流行的术语混淆:许多人称任何函数声明为“原型”,而实际上“函数声明”与“原型”并不相同。


查看完整回答
反对 回复 2019-06-15
?
慕工程0101907

TA贡献1887条经验 获得超5个赞

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

在使用这个语法的时候,人们有时会发现这样的函数

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

的类型,实际上是一个有效的定义。foop,和q默认为int.


查看完整回答
反对 回复 2019-06-15
?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

这只是一个古老的语法,早于你可能更熟悉的“ANSI C”语法。这叫“K&R C“,典型的。

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


查看完整回答
反对 回复 2019-06-15
  • 3 回答
  • 0 关注
  • 1093 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信