K&R中的C函数声明

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

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

 main(a, b, c, d){ printf("%d", d); } foo(a, b){ a = 2; b = 'z'; } 

如果这是一个问题,请在评论部分提供链接。 我找不到类似的东西。

编辑

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

“K&R C”是指1978年第一版Kernighan&Ritchie的书“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”规则(同时保留旧式声明和定义语法)。

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

由于这是main的定义,还有另一个问题。 标准只为main指定了两种forms(一种没有参数,一种有两个参数, argcargv )。 实现可以支持其他forms,但是具有四个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编程中使用这样的语法。

优秀!

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

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

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

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

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

默认参数是C中的int类型,关于K&R语法请看这里和这里 。

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

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

 main(int a,int b,int c,int d){printf("%d", d);} foo(int a,int b){a=2; b='z';}