有没有办法定义宏检查另一个宏定义和非零或未定义或定义为零?
我最近遇到的问题是,如果用作标志,不同的人会以不同的方式定义他们的宏。编译时会定义一些没有值的宏(例如。-DDEBUG
),有些则将其设置为非零(例如。-DDEBUG=1
)。
我实际上发现了类似的代码:(defined(macro ## _SET) && (macro ## _SET))
。这项工作的解决方案是连接##
,它阻止宏扩展。有办法吗?
环境
使用GNU ISO C99(arm-none-eabi-*
)的GNU Arm嵌入式工具链(std=gnu99
)。
答案 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)
意思是,除非依赖编译器特定的非标准扩展,否则通常无法在某些嵌套宏扩展中隐藏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
}