我正在开发一个嵌入式项目,并且在项目的源代码(在 C 中)中包含一个用于检查以太网类型是轮询还是中断的函数。我们有如下功能
unsigned char mode(void);
unsigned char xmode(void)
{
if(mode())
return 1;
return 0;
}
函数 mode() 没有主体。当函数 mode() 被函数 xmode() 调用时会发生什么?
扩展之前的答案。
这不是一个“空”函数,它是一个原型。
编译器使用它为您拥有主体的函数输出目标代码。它需要能够正确设置函数调用并确保它处理任何转换等。目标代码将包含对函数的引用,链接器将用正确的值替换这些引用。
这也意味着编译器可以为您进行错误检查并获得比链接器更多的信息。有趣的是,C 标准曾经允许隐式声明函数。
(为了清楚起见,这是简化的。)
在上面的代码unsigned char mode(void);
中告诉编译器该函数mode()
存在并且它不接受任何参数但返回一个unsigned char
.
这并没有真正定义功能。它只定义了调用它的方式。这个东西叫做a function prototype
。
该函数mode()
稍后在同一个文件或另一个文件(可能是程序集文件)中定义。
函数原型的常见用途之一是实现递归。
考虑函数a()
和b()
,每个调用另一个,并在同一个文件中定义:
void a()
{
b();
}
void b()
{
a();
}
当编译器看到b()
内部时a()
,它根本不知道b()
真正是什么或应该是什么。显然,如果您更改定义a()
and的顺序b()
,您将遇到同样的问题,但现在a()
不会在b()
.
为了解决这个问题,你添加了一个原型:
void b();
void a()
{
b();
}
void b()
{
a();
}
现在编译器将知道什么b()
是(函数)并知道如何调用和使用它。
这将无法链接,或者您正在链接的文件包含实际mode()
功能。