使用#define强制调用函数

use*_*687 1 c c-preprocessor

假设我有以下代码:

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()必须在任何其他函数之前首先被调用。我可以用一些全局布尔变量或其他东西来做到这一点,但我希望有一种预处理器方法可以做到这一点。有没有?

fuz*_*fuz 5

预处理器在代码被编译器处理之前运行。它所做的一切都发生在代码运行之前。预处理器没有函数或变量的概念,它只是将输入复制到输出并在两者之间扩展宏(它实际上做了更多的事情,但这并不重要)。对于您的代码,预处理器基本上会看到以下内容:

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)