K& R中的C函数声明

时间:2013-08-24 18:23:51

标签: c

我不熟悉K& R风格的功能声明。

编译之后,带有警告(仅与使用-Wall的main的返回值相关)但是使用的变量的数据类型是什么?

main(a, b, c, d){
    printf("%d", d);
}

foo(a, b){
     a = 2; 
     b = 'z';
}

如果之前有人询问,请在评论部分提供链接。我找不到类似的东西。

修改

我刚刚遇到了混淆的C代码,它使用了这些代码 但我可以向你保证,我不会在C编程中使用这样的语法。

4 个答案:

答案 0 :(得分:19)

“K& R C”是指1978年第一版Kernighan& Cn定义的语言。里奇的书“The C Programming Language”。

在K& R(即,ANSI之前的)C中,通常可以在没有显式类型的情况下声明实体,并且默认类型为int。这可以追溯到C的祖先语言,B和BCPL。

main(a,b,c,d){
    printf("%d", d);
}

几乎相当于:

int main(int a, int b, int c, int d) {
    printf("%d", d);
}

旧的语法在ANSI C(1989)和ISO C(1990)中仍然合法但过时,但1999 ISO C标准删除了“隐式int”规则(同时保留了旧式声明和定义语法)。 / p>

请注意,我说它几乎等价。它在定义时基本相同,但作为声明,它不提供参数类型信息。使用旧式定义,不需要诊断具有错误数量或类型的参数的调用;它只是未定义的行为。使用可见原型,不匹配的参数会触发编译时诊断 - 并且在可能的情况下,参数会隐式转换为参数类型。

由于这是main的定义,还有另一个问题。该标准仅为main指定了两种形式(一种不带参数,一种带有两个参数,argcargv)。实现可以支持其他形式,但是具有四个int参数的实现可能不是其中之一。因此,程序的行为是不确定的。实际上,d可能在初始调用时会有一些垃圾值。 (是的,在C中允许递归调用main,但几乎不是一个好主意。)

foo(a,b){
    a = 2;
    b = 'z';
}

这几乎相当于:

int foo(int a, int b) {
    a = 2;
    b = 'z';
}

(请注意,'z'的类型为int,而不是char类型。)

同样,旧表单不会给你参数类型检查,所以调用如:

foo("wrong type and number of arguments", 1.5, &foo);

无需诊断。

底线:了解K& R风格的函数声明和定义是如何工作的,这很好。仍然有旧的代码使用它们,即使在C2011中它们仍然合法(但是过时)(尽管没有“隐式int”规则)。但是编写使用它们的代码几乎没有任何理由(除非你使用一个非常旧的编译器,但这种情况很少见,而且变得越来越罕见。)

  

但我可以向你保证,我不会在C编程中使用这样的语法。

出色!

答案 1 :(得分:6)

在K& R样式函数定义中,参数的类型由一组专用声明指定,这些声明放置在函数“signature”本身和实际函数体之间。例如,这个函数定义

void foo(a, b, c)
double a;
char b;
{
  ...
}

使用doublecharint类型的参数。这实际上是“隐式int”规则发挥作用的地方和方式:由于上述声明列表未提及参数c,因此假定其类型为int

请注意重要的细节,我认为其他答案还不够清楚:参数c的类型int不是因为函数参数列表中缺少类型,而是因为它不是在函数“signature”之后的函数体之前的声明符序列中提到。在K& R风格的声明中,函数参数列表中总是缺少类型(这是K& R声明的定义特征),但它并不意味着假定所有参数都具有类型int

P.S。请注意,C99仍支持K& R样式声明,但由于C99禁止“隐式int”规则,因此它要求您在“签名”功能之后在该声明列表中提及所有函数参数。由于这个原因,上面的例子不会在C99中编译。必须将int c添加到声明列表中。

答案 2 :(得分:3)

在C89中,默认变量类型为int:它被定义为 implicit int 。该规则已在C99中撤销。

在您的示例中,它编译为:

main(int a,int b,int c,int d){printf("%d", d);}

foo(int a,int b){a=2; b='z';}

答案 3 :(得分:3)

默认参数是C中的int类型,约为K& R语法请查看herehere