我是一名Java程序员,我学到了一点C ++,现在我正在为我的工作学习一点C语言。 我无法理解关于函数声明/定义和相关函数调用的C行为。 从K& R我知道在C中(与C ++非常不同)我可以调用一个先前未声明的函数,并且编译器假定该类型的隐式声明:
int main()
{
function(10); // implicit function declaration ( int function() )
}
我知道这样的声明意味着一个函数接受任何类型的固定但无限数量的参数(只要每个调用与其他调用一致)。在C89之前我知道这是K& R C,但我想知道它是如何工作的。 现在,我有这个测试代码,我无法理解:
#include <stdio.h>
function();
int main()
{
printf("hello %d",function(1,2,3));
implicit(11,12,32); // implicit function declaration ( implicit() )
}
int implicit(int b)
{
}
function(int a)
{
}
在function
的情况下声明(返回类型假定为int,没有关于参数的假设)确实匹配定义(编译器发出警告)但是如果我用错误的参数调用函数,它汇编!
函数implicit
也是如此。
我无法理解......
答案 0 :(得分:3)
你必须要记住的是,在声明和定义方面,编译几乎是顺序的。当编译器处理function
的调用时,它所声明的是声明,正如你所说的那样,对参数没有任何假设,这意味着你可以使用你喜欢的任何参数调用该函数。当编译器看到定义时,它不会返回发出有关调用的错误,但它可能会发出警告。
对于implicit
函数,当编译器第一次看到它时,它将假定参数是在推断声明时在调用中传递的参数。在它稍后看到声明之前,它不会知道任何其他事情,并且可能会发出警告。
使用多个或几个参数调用函数会导致未定义的行为,这就是隐式声明的函数如此危险的原因,以及在声明函数时使用空参数列表。< / p>
答案 1 :(得分:0)
真的没什么好理解的。这是一种遗留的C行为,这是一种非常宽松的语言。只要编译器可以生成汇编指令,它就会很乐意编译你的代码,并留给你清理混乱。
这就是为什么它会在你的情况下编译。编译器可以生成调用函数的指令 - 所以它按照要求进行。