gal*_*ets 35 c++ visual-c++ c-preprocessor
使用C++预处理程序指令,是否可以测试是否已定义预处理程序符号但没有值?像这样的东西:
#define MYVARIABLE
#if !defined(MYVARIABLE) || #MYVARIABLE == ""
... blablabla ...
#endif
Run Code Online (Sandbox Code Playgroud)
编辑:我这样做的原因是因为我正在处理的项目应该从环境中获取一个字符串/DMYSTR=$(MYENVSTR),这个字符串可能是空的.如果用户忘记定义此字符串,我想确保项目无法编译.
Mar*_*ork 40
Soma宏魔法:
#define DO_EXPAND(VAL) VAL ## 1
#define EXPAND(VAL) DO_EXPAND(VAL)
#if !defined(MYVARIABLE) || (EXPAND(MYVARIABLE) == 1)
Only here if MYVARIABLE is not defined
OR MYVARIABLE is the empty string
#endif
Run Code Online (Sandbox Code Playgroud)
请注意,如果在命令行上定义MYVARIABLE,则默认值为1
g++ -DMYVARIABLE <file>
Run Code Online (Sandbox Code Playgroud)
这里MYVARIABLE的值是1
g++ -DMYVARIABLE= <file>
Run Code Online (Sandbox Code Playgroud)
这里MYVARIABLE的值是空字符串
#define DO_QUOTE(X) #X
#define QUOTE(X) DO_QUOTE(X)
#define MY_QUOTED_VAR QUOTE(MYVARIABLE)
std::string x = MY_QUOTED_VAR;
std::string p = QUOTE(MYVARIABLE);
Run Code Online (Sandbox Code Playgroud)
Geo*_*che 10
如果用户忘记定义此字符串,我想确保项目无法编译.
虽然我在之前的构建步骤中检查了这一点,但您可以在编译时执行此操作.使用Boost简洁:
#define A "a"
#define B
BOOST_STATIC_ASSERT(sizeof(BOOST_STRINGIZE(A)) > 1); // succeeds
BOOST_STATIC_ASSERT(sizeof(BOOST_STRINGIZE(B)) > 1); // fails
Run Code Online (Sandbox Code Playgroud)
小智 10
我没有看到这个问题的解决方案,但我很惊讶它不常用.它似乎适用于Xcode Objc.区分"无值定义"和"定义集0"
#define TRACE
#if defined(TRACE) && (7-TRACE-7 == 14)
#error TRACE is defined with no value
#endif
Run Code Online (Sandbox Code Playgroud)
Mehrad的答案必须扩展才能使其起作用。还有他的评论
/ * MYVARI(A)BLE在这里未定义* /
是不正确的; 要测试未定义的变量,可以使用简单的test #ifndef MYVARIABLE。
然而,经过这样的测试,他的表情导致了对原始问题的正确解决。我测试了此代码对于宏MYVARIABLE的未定义,已定义但为空和非空的值有效:
#ifndef MYVARIABLE
/* MYVARIABLE is undefined here */
#elif ~(~MYVARIABLE + 0) == 0 && ~(~MYVARIABLE + 1) == 1
/* MYVARIABLE is defined with no value here */
#else
/* MYVARIABLE is defined here */
#endif
Run Code Online (Sandbox Code Playgroud)
该#elif语句的~(~MYVARIABLE + 0) == 0 && ~(~MYVARIABLE + 1) == 1 工作方式如下:
MYVARIABLE定义但为空时,它将扩展为~(~+0) == 0 && ~(~+1) == 1,从而得出结果0==0 && 1==1(双重否定是身份运算符)。MYVARIABLE定义为数值(例如n)时,它将扩展为~(~n+0)==0 && ~(~n+1)==1。在的左侧&&,表达式的~(~n+0)==0计算结果为n==0。但是,用n==0,右手边的计算结果为~(~0+1)==1,〜0为-1对~(-1+1)==1,然后~0==1最后-1==1,这显然是错误的。MYVARIABLE定义为非数字值时,预编译器将所有未知符号减少为0,并且我们再次得到n == 0的前一种情况。我完整的测试代码(另存为文件test.c):
#include <stdio.h>
int main() {
printf("MYVARIABLE is "
#ifndef MYVARIABLE
"undefined"
#elif ~(~MYVARIABLE + 0) == 0 && ~(~MYVARIABLE + 1) == 1
"defined without a value"
#else
"defined with this value : %i", MYVARIABLE
#endif
);
printf("\n");
}
Run Code Online (Sandbox Code Playgroud)
使用GNU预处理程序cpp,您可以尝试查看生成的代码:
# undefined
cpp test.c
#defined without a value
cpp -DMYVARIABLE= test.c
#defined wit an implicit value 1
cpp -DMYVARIABLE test.c
#defined wit an explicit value 1
cpp -DMYVARIABLE=1 test.c
#defined wit an explicit value a
cpp -DMYVARIABLE=a test.c
Run Code Online (Sandbox Code Playgroud)
或编译和执行的输出(在某些Linux下)
$ gcc -o test test.c ; ./test
MYVARIABLE is undefined
$ gcc -DMYVARIABLE= -o test test.c ; ./test
MYVARIABLE is defined without a value
$ gcc -DMYVARIABLE -o test test.c ; ./test
MYVARIABLE is defined with this value : 1
$ gcc -DMYVARIABLE=1 -o test test.c ; ./test
MYVARIABLE is defined with this value : 1
$ gcc -DMYVARIABLE=a -o test test.c ; ./test
test.c: In function ‘main’:
<command-line>:0:12: error: ‘a’ undeclared (first use in this function)
...
Run Code Online (Sandbox Code Playgroud)
在最后一次运行中,MYVARIABLE被定义为“ a”,该错误不是宏定义中的错误;宏正确地导致了最后一种情况,“用此值定义...”。但是此值是“ a”,而在代码中未定义“ a”,因此编译器或过程必须发出信号。
这样,最后一种情况就是一个很好的例子,说明了原始问题的意图为何非常危险:用户可以通过宏在要编译的代码中引入任何程序行序列。检查是否未引入此类代码,需要对宏进行有效值的更多检查。可能需要完整的脚本,而不是将此任务留给预处理。在这种情况下,在预处理中检查它又有什么用?