我不熟悉K&R风格的函数声明。
以下代码可以编译通过,但会有一个警告(只与-Wall
相关的主函数返回值),但是使用的变量的数据类型是什么?
main(a, b, c, d){
printf("%d", d);
}
foo(a, b){
a = 2;
b = 'z';
}
如果这个问题以前已经被问过,请在评论区提供链接。我找不到相似的东西。
编辑
我刚刚遇到了一段混淆的C代码,其中使用了这些语法。
但我可以保证,在C编程中我不会使用这样的语法。
我不熟悉K&R风格的函数声明。
以下代码可以编译通过,但会有一个警告(只与-Wall
相关的主函数返回值),但是使用的变量的数据类型是什么?
main(a, b, c, d){
printf("%d", d);
}
foo(a, b){
a = 2;
b = 'z';
}
如果这个问题以前已经被问过,请在评论区提供链接。我找不到相似的东西。
编辑
我刚刚遇到了一段混淆的C代码,其中使用了这些语法。
但我可以保证,在C编程中我不会使用这样的语法。
“K&R C”是指Kernighan & Ritchie的书“The C Programming Language”的1978年第一版所定义的语言。
在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) 中,“implicit int”规则仍然是合法但已经过时的,但是 1999 年的 ISO C 标准取消了该规则(同时保留了旧式声明和定义语法)。
需要注意的是,我说它“几乎”等同。从定义的角度来看,它本质上是相同的,但从声明的角度来看,它不提供参数类型信息。使用旧式定义时,对于参数数量或类型不正确的调用无需进行诊断; 它只是未定义行为。与可见原型不同,不匹配的参数会触发编译时诊断 - 并且可能会将参数隐式转换为参数类型。
由于这是对 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中仍然合法(但已过时,没有“implicit int”规则)。但是几乎没有任何好理由编写使用它们的代码(除非你被迫使用非常旧的编译器,但这种情况很罕见并且越来越少)。
但我可以向您保证,在C编程中我不会使用这样的语法。
太好了!
void foo(a, b, c)
double a;
char b;
{
...
}
该函数使用参数类型为double
, char
和int
。这实际上就是"隐式int"规则的发挥方式和位置:由于参数c
在上述声明列表中没有被提及,它被假定为具有类型int
。
请注意一个重要的细节,我认为其他答案没有很清楚地表明:参数c
的类型为int
不是因为函数参数列表中缺少该类型,而是因为在函数"签名"(函数体之前)后面的声明符序列中没有提到它。在K&R风格的声明中,函数参数列表中总是缺少类型(这是K&R声明的定义特征),但这并不意味着所有参数都被假定为具有类型int
。
附注:请注意,C99仍然支持K&R风格的声明,但由于C99禁止了"隐式int"规则,因此需要在函数"签名"后的声明列表中提及所有函数参数。由于上述示例没有在声明列表中添加int c
,所以在C99中不会编译通过。
int
类型? - P0Wb
的类型并不是默认为int
,只是因为函数参数列表中缺少了它的类型。为了确定b
的类型,编译器会继续查找,而不是草率下结论。它会发现char b
的声明,并意识到b
应该是一个char
类型。 - AnT stands with Russiaint
:它被定义为隐式int。这个规则在C99中被撤销了。main(int a,int b,int c,int d){printf("%d", d);}
foo(int a,int b){a=2; b='z';}
main(a,b,c,d) int a,b,c,d;
的形式。两者之间的差别微妙,但在使用 K&R 语法时,你可以做一些愚蠢的事情,比如用任何数量和类型的参数调用这些函数而没有警告(例如,参见 https://dev59.com/LGMl5IYBdhLWcg3wsIuA)。 - nneonneofoo(a,b,c){printf("%s-%s-%s", a,b,c); } main(a,b,c,d){foo("this", "shouldn't", "work");}
它就是能够正常运行。 - P0W-Wall
会抛出警告。 - P0Wprintf
的警告,提示警告:格式参数不是指针(arg 2)
。 - Dayal rai
foo("this", "shouldn't", "work")
。 - nneonneofoo(a,b,c){printf("%s-%s-%s", a,b,c); } main(a,b,c,d){foo("this", "shouldn't", "work");}
编译并打印输出! - P0W