通用预处理器宏启用检查

时间:2017-12-13 12:18:15

标签: c gcc macros c-preprocessor

有没有办法定义宏检查另一个宏定义非零未定义定义为零

我最近遇到的问题是,如果用作标志,不同的人会以不同的方式定义他们的宏。编译时会定义一些没有值的宏(例如。-DDEBUG),有些则将其设置为非零(例如。-DDEBUG=1)。

我实际上发现了类似的代码:(defined(macro ## _SET) && (macro ## _SET))。这项工作的解决方案是连接##,它阻止宏扩展。有办法吗?

环境

使用GNU ISO C99(arm-none-eabi-*)的GNU Arm嵌入式工具链(std=gnu99)。

3 个答案:

答案 0 :(得分:2)

您可以对宏名称(如果未定义)或扩展(如果已定义)进行字符串化,然后检查它。这个计划:

#define DefinedBlank
#define DefinedZero     0
#define DefinedOne      1

#define Stringify(x)    #x
#define Enabled(x)      (Stringify(x)[0] == 0 || Stringify(x)[0] == '1')

#include <stdio.h>

int main(void)
{
    const char *String[] = { "not ", "" };

    printf("Undefined is %senabled.\n",    String[Enabled(Undefined)]);
    printf("DefinedBlank is %senabled.\n", String[Enabled(DefinedBlank)]);
    printf("DefinedZero is %senabled.\n",  String[Enabled(DefinedZero)]);
    printf("DefinedOne is %senabled.\n",   String[Enabled(DefinedOne)]);
}

打印:

Undefined is not enabled.
DefinedBlank is enabled.
DefinedZero is not enabled.
DefinedOne is enabled.

Apple LLVM在编译时评估条件,因此您可以使用if Enabled(foo) { code… },如果未启用code…foo将不会包含在可执行文件中。 (但是,它必须在语法和语法上都是正确的。)

如果你想要比未定义,空白,0或1更复杂的区别,那么你可以编写一个任意例程来检查字符串并返回结果。当然,编译器不太可能优化它。

答案 1 :(得分:1)

引用一些GCC文档:If the defined operator appears as a result of a macro expansion, the C standard says the behavior is undefined. GNU cpp treats it as a genuine defined operator and evaluates it normally.

意思是,除非依赖编译器特定的非标准扩展,否则通常无法在某些嵌套宏扩展中隐藏hpack宏测试。

所以,我能想出的最好的是两部分测试(https://stackoverflow.com/a/13262601/5265292给了我基本的想法):

{
  "verbose": true,
  "ignore": ["src/*"]
}

完整样本:

Right("              " & {Inv.No},15)

正如所指出的,您可能能够利用GNUCC特定的宏扩展来在defined测试中进行// if x is empty: 1 - -1 == 2 // if x is zero: 1 - 0 - 1 == 0 // if x is any other number: 1 - x - 1 == -x #define ENABLED(x) (1 - x -1 != 0) #if defined FLAG && ENABLED(FLAG) // execute if FLAG is defined as not-zero #endif 测试,但我没有GCC和手头的时间检查这方面,我更喜欢便携式解决方案。

答案 2 :(得分:0)

这为宏未定义,定义但空白,定义为“0”或定义为“1”的情况提供预处理器测试。它没有区分宏的其他定义(例如,定义为“2”的宏将被报告为未启用):

#define EnabledTest     1
#define EnabledTest0    0
#define EnabledTest1    1
#define EnabledPaste(x) EnabledTest ## x
#define Enabled(x)      EnabledPaste(x)


#define DefinedBlank
#define DefinedZero     0
#define DefinedOne      1


#include <stdio.h>

int main(void)
{
    #if Enabled(Undefined)
        printf("Undefined is enabled.\n");
    #endif
    #if Enabled(DefinedBlank)
        printf("DefinedBlank is enabled.\n");
    #endif
    #if Enabled(DefinedZero)
        printf("DefinedZero is enabled.\n");
    #endif
    #if Enabled(DefinedOne)
        printf("DefinedOne is enabled.\n");
    #endif
}

输出是:

DefinedBlank is enabled.
DefinedOne is enabled.

此外,我们可以将其与grek40的想法结合起来,将其概括为未定义,已定义但为空白,并定义为仅在x中代替1 - x - 1进行评估的字符串:

#define EnabledTest     1
#define EnabledPaste(x) EnabledTest ## x
#define Enabled(x)      (EnabledPaste(x)) || (1 - x - 1)


#define DefinedBlank
#define DefinedZero     0
#define DefinedOne      1


#include <stdio.h>

int main(void)
{
    #if Enabled(Undefined)
        printf("Undefined is enabled.\n");
    #endif
    #if Enabled(DefinedBlank)
        printf("DefinedBlank is enabled.\n");
    #endif
    #if Enabled(DefinedZero)
        printf("DefinedZero is enabled.\n");
    #endif
    #if Enabled(DefinedOne)
        printf("DefinedOne is enabled.\n");
    #endif
}