我不熟悉K& R风格的功能声明。
编译之后,带有警告(仅与使用-Wall
的main的返回值相关)但是使用的变量的数据类型是什么?
main(a, b, c, d){
printf("%d", d);
}
foo(a, b){
a = 2;
b = 'z';
}
如果之前有人询问,请在评论部分提供链接。我找不到类似的东西。
修改
我刚刚遇到了混淆的C代码,它使用了这些代码 但我可以向你保证,我不会在C编程中使用这样的语法。
答案 0 :(得分:19)
在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
指定了两种形式(一种不带参数,一种带有两个参数,argc
和argv
)。实现可以支持其他形式,但是具有四个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;
{
...
}
使用double
,char
和int
类型的参数。这实际上是“隐式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)