C预处理器 - 根据另一个宏不同地定义宏

时间:2017-08-25 09:03:14

标签: c macros preprocessor

我有一个调试设置,您可以在makefile中设置各种调试标志,然后在每个源文件中设置:

#ifdef DEBUG_FLAG
#    define DEBUGGING(...) Something(__VA_ARGS__)
#else
#    define DEBUGGING(...) do {} while(0)
#endif

我想通过让源文件说出如下内容来使这更简洁:

#define DEBUGGING(...) DEBUG_HELP( DEBUG_FLAG, Something(__VA_ARGS__) )

其中DEBUG_HELP在标头中定义,具有相同的最终结果,即使用DEBUGGING宏将导致Something被调用,仅在DEBUG_FLAG被定义时为非零。如果根本没有定义DEBUG_FLAG那么代码仍应编译,只是不要调用Something

这有可能吗?

到目前为止,我的尝试,在根本没有定义DEBUG_FLAG的情况下,我无法找到一种不会出现编译错误的方法。

2 个答案:

答案 0 :(得分:1)

从名义动物对类似问题Test if preprocessor symbol is defined inside macro的回答中删除,以下方法应该起作用。如果foo.c是:

#define STRINGIFY(x) #x

#define DEBUG_HELP(flag, action)                      \
    do {                                              \
        if (strcmp(STRINGIFY(flag), #flag)) &&        \
            strcmp(STRINGIFY(flag), "0")) {           \
            action;                                   \
        }                                             \
    } while (0)

#define DEBUGGING(...) DEBUG_HELP(DEBUG_FLAG, printf(__VA_ARGS__))

DEBUGGING("%d\n", 42);

然后:

$ gcc -E -P foo.c               
do { if (strcmp("DEBUG_FLAG", "DEBUG_FLAG")) && strcmp("DEBUG_FLAG", "0")) { printf("%d\n", 42); } } while (0);
$ gcc -E -P foo.c -DDEBUG_FLAG=0
do { if (strcmp("0", "DEBUG_FLAG")) && strcmp("0", "0")) { printf("%d\n", 42); } } while (0);
$ gcc -E -P foo.c -DDEBUG_FLAG  
do { if (strcmp("1", "DEBUG_FLAG")) && strcmp("1", "0")) { printf("%d\n", 42); } } while (0);
$ gcc -E -P foo.c -DDEBUG_FLAG=bar
do { if (strcmp("bar", "DEBUG_FLAG")) && strcmp("bar", "0")) { printf("%d\n", 42); } } while (0);

因此,在DEBUG_FLAG未定义或设置为0的情况下,if条件将为false。如果DEBUG_FLAG是其他任何东西,除了一个例外,条件将为true。一个例外是您有以下情况:

#define DEBUG_FLAG DEBUG_FLAG

strcmp应该在编译时使用gcc,Clang和MSVC进行评估,尽管我找不到任何保证。作为测试,请参见以下代码:

#include <string.h>
int main(void) {
    if (strcmp("foo", "foo"))
        return 888;
    if (&"foo" != &"foo") // '&' for Clang
        return 999;
    return 777;
}

https://godbolt.org/g/2kVShr处编译。

答案 1 :(得分:0)

您可以将条件放在单独的头文件中。

debug_help.h

#ifdef DEBUG_FLAG
    #define DEBUG_HELP(...) __VA_ARGS__
#else
    #define DEBUG_HELP(...) do {} while(0)
#endif

some_source_module.c

#include "debug_help.h"
#define DEBUGGING(...) DEBUG_HELP(puts(__VA_ARGS__))

DEBUGGING("test"); // expands to puts("test"); when DEBUG_FLAG is defined

如果您可以让编译器为每个编译单元自动包含它,则可以省略#include "debug_help.h"