使用#define强制调用函数

时间:2014-11-29 13:01:23

标签: 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
}

然后在main()中我将这些函数称为如下:

int main(void)
{
    test();
    test2();
}

即使我先拨打test(),然后#define INIT_DONE我仍然会:

  

"首先调用函数test()!"

编译器出错。

那么,我怎样才能实现,在任何其他函数之前必须首先调用函数test()。我可以使用一些全局布尔变量或其他东西,但我希望有一个预处理器方法来做到这一点。有吗?

1 个答案:

答案 0 :(得分:4)

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

gibberish

    #define INIT_DONE

    // comment

more gibberish

    #ifndef INIT_DONE
    #error "Call function test() first!"
    #endif
    // another comment

even more gibberish

预处理器遍历它并首先看到#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);
    /* ... */
}

由于预处理程序在程序运行之前运行,因此通常无法在预处理程序中执行此操作。您也可以退出这些检查,并强调初始化需要在您的文档中完成。另一种方法是根本不需要程序员初始化,这取决于具体情况:

static int init_done = 0;

/* same initialization function as before */
void test(void)
{
    init_done = 1;
    /* ... */
}

void test2(void)
{
    if (!init_done)
        test();

    /* ... */
}