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(一种没有参数,一种有两个参数, argc
和argv
)。 实现可以支持其他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; { ... }
使用double
, char
和int
类型的参数。 这实际上是“隐式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';}