假设我有以下代码:
void test(void)
{
#define INIT_DONE
//General initialization stuff
}
void test2(void)
{
#ifndef INIT_DONE
#error "Call function test() first!"
#endif
// Specific initialization stuff
}
Run Code Online (Sandbox Code Playgroud)
然后main()
我按如下方式调用这些函数:
int main(void)
{
test();
test2();
}
Run Code Online (Sandbox Code Playgroud)
即使我test()
先打电话,#define INIT_DONE
我仍然得到:
“首先调用函数 test()!”
编译器上的错误。
那么,我怎样才能实现该函数test()
必须在任何其他函数之前首先被调用。我可以用一些全局布尔变量或其他东西来做到这一点,但我希望有一种预处理器方法可以做到这一点。有没有?
预处理器在代码被编译器处理之前运行。它所做的一切都发生在代码运行之前。预处理器没有函数或变量的概念,它只是将输入复制到输出并在两者之间扩展宏(它实际上做了更多的事情,但这并不重要)。对于您的代码,预处理器基本上会看到以下内容:
gibberish
#define INIT_DONE
// comment
more gibberish
#ifndef INIT_DONE
#error "Call function test() first!"
#endif
// another comment
even more gibberish
Run Code Online (Sandbox Code Playgroud)
预处理器遍历该过程并首先看到#define INIT_DONE
,因此它将宏定义INIT_DONE
为 1;以后每次出现INIT_DONE
都会被替换为 1,在编译器看到代码之前丢弃。然后它看到#ifndef INIT_DONE
, 但INIT_DONE
已经定义了,因此它跳过了后面的位。
关键是预处理器在任何时候都不关心正在执行的内容。要做你想做的事,使用这样的东西:
#include <assert.h>
/* only visible in the source code form where test() and test2() are defined */
static int init_done = 0;
void test(void)
{
init_done = 1;
/* ... */
}
void test2(void)
{
assert(init_done);
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
通常无法在预处理器中执行此操作,因为预处理器在程序运行之前运行。您也可以忽略这些检查,只强调需要在文档中完成初始化。另一种方法是根本不需要程序员进行初始化,这根据具体情况很有用:
static int init_done = 0;
/* same initialization function as before */
void test(void)
{
init_done = 1;
/* ... */
}
void test2(void)
{
if (!init_done)
test();
/* ... */
}
Run Code Online (Sandbox Code Playgroud)