If指令宏比较

If-directive macro comparison

为什么下面代码中的#if条件成立:

#include <iostream>
#define VALUE foo    

int main() {    
#if VALUE == bar
    std::cout << "WORKS!" << std::endl;
#endif // VALUE
}

page on cppreference.com 状态:

After all macro expansion and evaluation of defined and __has_include (since C++17) expressions, any identifier which is not a boolean literal is replaced with the number ​0​ (this includes identifiers that are lexically keywords, but not alternative tokens like and).

所以VALUE先替换成foo,然后foobar都替换成0.

#if 语句中,宏替换后剩余的任何标识符(truefalse 除外)都将替换为常量 0。所以你的指令变成

#if 0 == 0

这是真的。

这是因为 foobar 都没有被赋予任何定义或值 - 所以它们是相同的(即替换为“0”值)。编译器将对此发出警告。

MSVC 编译器(Visual Studio 2019)给出以下内容:

warning C4668: 'foo' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
warning C4668: 'bar' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'

所以 VALUE 被赋予值 '0'(foo 的默认值)并且 bar 也有 '0',所以 VALUE == bar 计算为 "TRUE."

类似地,clang-cl 给出以下内容:

warning : 'foo' is not defined, evaluates to 0 [-Wundef]
warning : 'bar' is not defined, evaluates to 0 [-Wundef]

要完成你想要的,试试这个:

#include <iostream>
#define DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

在这种情况下,您可以通过将 "define" 更改为 "undef" 来关闭调试语句。

#include <iostream>
#undef DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

您可能会发现您的编译器允许您在代码本身之外定义 DEBUG,此时您可以将代码缩减为

#include <iostream>

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

然后使用 -DDEBUG=0

等选项调用编译器

查看 Steve McConnell 的防御性编程一章,"Code Complete."