C++ 如何测试预处理器符号是否已#define'd但没有值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3781520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to test if preprocessor symbol is #define'd but has no value?
提问by galets
Using C++ preprocessor directives, is it possible to test if a preprocessor symbol has been defined but has no value? Something like that:
使用 C++ 预处理器指令,是否可以测试预处理器符号是否已定义但没有值?类似的东西:
#define MYVARIABLE
#if !defined(MYVARIABLE) || #MYVARIABLE == ""
... blablabla ...
#endif
EDIT:The reason why I am doing it is because the project I'm working on is supposed to take a string from the environment through /DMYSTR=$(MYENVSTR)
, and this string might be empty. I want to make sure that the project fails to compile if user forgot to define this string.
编辑:我这样做的原因是因为我正在处理的项目应该从环境中获取一个字符串/DMYSTR=$(MYENVSTR)
,并且这个字符串可能是空的。如果用户忘记定义这个字符串,我想确保项目无法编译。
回答by Martin York
Soma macro magic:
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
Note if you define MYVARIABLE on the command line the default value is 1
请注意,如果您在命令行上定义 MYVARIABLE,则默认值为 1
g++ -DMYVARIABLE <file>
Here the value of MYVARIABLE is 1
这里 MYVARIABLE 的值为 1
g++ -DMYVARIABLE= <file>
Here the value of MYVARIABLE is the empty string
这里 MYVARIABLE 的值是空字符串
The quoting problem solved:
引用问题解决了:
#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);
回答by Ian Brackenbury
I haven't seen this solution to the problem but am surprised it is not in common use . It seems to work in Xcode Objc. Distinguish between "defined with no value" and "defined set 0"
我还没有看到这个问题的解决方案,但很惊讶它不常用。它似乎在 Xcode Objc 中工作。区分“没有值定义”和“定义集0”
#define TRACE
#if defined(TRACE) && (7-TRACE-7 == 14)
#error TRACE is defined with no value
#endif
回答by Georg Fritzsche
I want to make sure that the project fails to compile if user forgot to define this string.
如果用户忘记定义这个字符串,我想确保项目无法编译。
While i'd check this in a previous build-step, you can do this at compile-time. Using Boost for brevity:
虽然我会在之前的构建步骤中进行检查,但您可以在编译时执行此操作。为简洁起见,使用 Boost:
#define A "a"
#define B
BOOST_STATIC_ASSERT(sizeof(BOOST_STRINGIZE(A)) > 1); // succeeds
BOOST_STATIC_ASSERT(sizeof(BOOST_STRINGIZE(B)) > 1); // fails
回答by db-inf
Mehrad's answer must be expanded to make it work. Also his comment
必须扩展 Mehrad 的答案才能使其发挥作用。还有他的评论
/* MYVARI(A)BLE is undefined here */
/* MYVARI(A)BLE 在这里未定义 */
is not correct; to test for an undefined variable, there is the simple test #ifndef MYVARIABLE
.
是不正确的; 要测试未定义的变量,有简单的 test #ifndef MYVARIABLE
。
After such test however, his expression leads to a correct solution of the original question. I tested that this code works, for undefined, defined but empty, and non-empty values of the macro 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
The #elif
statement ~(~MYVARIABLE + 0) == 0 && ~(~MYVARIABLE + 1) == 1
works as follows :
该#elif
语句的~(~MYVARIABLE + 0) == 0 && ~(~MYVARIABLE + 1) == 1
工作原理如下:
- When
MYVARIABLE
is defined but empty, it expands to~(~+0) == 0 && ~(~+1) == 1
, which works out0==0 && 1==1
(the double negation ~~ being an identity operator). - When
MYVARIABLE
is defined to a numeric value, say n, it expands to~(~n+0)==0 && ~(~n+1)==1
. On the left hand side of&&
, the expression~(~n+0)==0
evaluates ton==0
. But withn==0
, the right hand side evaluates to~(~0+1)==1
, with ~0 being -1 to~(-1+1)==1
, then~0==1
and finally-1==1
, which obviously is false. - When
MYVARIABLE
is defined to a non-numeric value, the precompiler reduces all unknown symbols to 0, and we get the previous case with n==0 once more.
- 当
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 的前一种情况。
My complete test code (save as file test.c) :
我的完整测试代码(另存为文件 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");
}
With the GNU preprocessor cppyou can experiment to see what code is produced:
使用 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
or output of compilation and execution (under some linux)
或编译和执行的输出(在某些 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)
...
In the last run, where MYVARIABLE is defined as 'a', the error is not an error in the macro definition; the macro is correctly lead to the last case, "defined with this value...". But this value being 'a', and 'a' not being defined in the code, the compiler or course has to signal this.
在上次运行中,其中 MYVARIABLE 被定义为 'a',该错误不是宏定义中的错误;宏正确导致最后一种情况,“用这个值定义......”。但是这个值是“a”,而“a”没有在代码中定义,编译器或课程必须发出信号。
In that way, the last case is a very good example of why the intent of the original question is very dangerous: via a macro the user can introduce any sequence of program lines in the code to be compiled. Checking that such code is not introduced, requires a lot more checking of the macro on valid values. Probably a full script is needed, instead of leaving this task to preprocessing. And in that case, what is the use of checking it in preprocessing too?
这样,最后一个案例是一个很好的例子,说明了为什么原始问题的意图非常危险:通过宏,用户可以在要编译的代码中引入任何程序行序列。检查未引入此类代码,需要对有效值的宏进行更多检查。可能需要一个完整的脚本,而不是将此任务留给预处理。在那种情况下,在预处理中检查它有什么用?
回答by mister why
You can use the BOOST_PP_IS_EMPTY
macro like so:
您可以BOOST_PP_IS_EMPTY
像这样使用宏:
#include <boost/preprocessor/facilities/is_empty.hpp>
#define MYVARIABLE
#if !defined(MYVARIABLE) || !BOOST_PP_IS_EMPTY(MYVARIABLE)
// ... blablabla ...
#endif
That did the trick for me. I shall add this macro is undocumented, so use it with caution.
这对我有用。我将添加此宏未记录,因此请谨慎使用。
回答by Reinderien
I don't think that this can be done. That being said, I don't see a need for it. When you make a preprocessor #define
symbol, you should establish a convention that either you define it as 1 or 0 for use in #if
, or you leave it blank.
我不认为这是可以做到的。话虽如此,我认为没有必要这样做。当您制作预处理器#define
符号时,您应该建立一个约定,将其定义为 1 或 0 以在 中使用#if
,或者将其留空。
回答by harper
You can't since the preprocessor can only check for a numeric value. Your string compare is not covered by preprocessor syntax.
您不能,因为预处理器只能检查数值。预处理器语法未涵盖您的字符串比较。
回答by Kris Morness
#if MYVARIABLE==0
My answer must be at least 30 chars, so that should do it!
#if MYVARIABLE==0
我的答案必须至少为 30 个字符,所以应该这样做!
回答by user541686
For integer-only macros...
对于仅限整数的宏...
You can use a hack with no extra macros:
您可以使用没有额外宏的 hack:
#if ~(~MYVARIABLE + 0) == 0 && ~(~MYVARIABLE + 1) == 1
/* MYVARIBLE is undefined here */
#endif