C 函数定义和声明
C function definition and declaration
我是一名 Java 程序员,我学过一点 C++,现在我正在为我的工作学习一点 C。
我无法理解有关函数 declaration/definition 和相关函数调用的 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
的情况下,声明(return 类型被假定为 int,没有关于参数的假设)确实匹配定义(编译器发出警告)但是如果我调用带有错误参数的函数,它编译!
与函数 implicit
相同。
看不懂..
您必须记住的是,在涉及声明和定义时,编译几乎是连续的。当编译器处理对 function
的调用时,它所拥有的只是声明,正如您所说,对参数没有任何假设,这意味着您可以使用您喜欢的任何参数调用该函数。当编译器看到定义时,它不会返回发出有关调用的错误,但它可能会发出警告。
至于 implicit
函数,当编译器第一次看到它时,它会假定参数是您在推导声明时在调用中传递的内容。同样,在它后来看到声明之前,它不会知道任何其他事情,然后可能会发出警告。
调用带有太多或很少参数的函数会导致未定义的行为,这就是隐式声明的函数以及使用空参数列表如此危险的原因声明函数时。
实在是没什么看不懂。这是一种遗留的 C 行为,是一种极其松散的语言。只要编译器能生成汇编指令,它会很乐意编译你的代码,交给你收拾残局。
这就是它在您的案例中编译的原因。编译器可以生成调用该函数的指令 - 所以它会按要求执行。
我是一名 Java 程序员,我学过一点 C++,现在我正在为我的工作学习一点 C。 我无法理解有关函数 declaration/definition 和相关函数调用的 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
的情况下,声明(return 类型被假定为 int,没有关于参数的假设)确实匹配定义(编译器发出警告)但是如果我调用带有错误参数的函数,它编译!
与函数 implicit
相同。
看不懂..
您必须记住的是,在涉及声明和定义时,编译几乎是连续的。当编译器处理对 function
的调用时,它所拥有的只是声明,正如您所说,对参数没有任何假设,这意味着您可以使用您喜欢的任何参数调用该函数。当编译器看到定义时,它不会返回发出有关调用的错误,但它可能会发出警告。
至于 implicit
函数,当编译器第一次看到它时,它会假定参数是您在推导声明时在调用中传递的内容。同样,在它后来看到声明之前,它不会知道任何其他事情,然后可能会发出警告。
调用带有太多或很少参数的函数会导致未定义的行为,这就是隐式声明的函数以及使用空参数列表如此危险的原因声明函数时。
实在是没什么看不懂。这是一种遗留的 C 行为,是一种极其松散的语言。只要编译器能生成汇编指令,它会很乐意编译你的代码,交给你收拾残局。
这就是它在您的案例中编译的原因。编译器可以生成调用该函数的指令 - 所以它会按要求执行。