【发布时间】:2020-07-01 21:04:31
【问题描述】:
为什么满足以下代码中的#if 条件:
#include <iostream>
#define VALUE foo
int main() {
#if VALUE == bar
std::cout << "WORKS!" << std::endl;
#endif // VALUE
}
【问题讨论】:
标签: c++ c-preprocessor
为什么满足以下代码中的#if 条件:
#include <iostream>
#define VALUE foo
int main() {
#if VALUE == bar
std::cout << "WORKS!" << std::endl;
#endif // VALUE
}
【问题讨论】:
标签: c++ c-preprocessor
在定义和 __has_include 的所有宏扩展和评估之后 (C++17 起) 表达式,任何不是布尔值的标识符 文字被数字 0 替换(这包括标识符 它们是词法关键字,但不是替代标记,如 and)。
所以VALUE首先被替换为foo,然后foo和bar都被替换为0。
【讨论】:
在#if 语句中,宏替换后保留的任何标识符(true 和false 除外)都将替换为常量0。所以你的指令变成了
#if 0 == 0
这是真的。
【讨论】:
这是因为 foo 和 bar 都没有被赋予任何定义或值 - 所以它们是相同的(即替换为“0”值)。编译器会对此给出警告。
MSVC 编译器 (Visual Studio 2019) 提供以下功能:
警告 C4668:'foo' 未定义为预处理器宏,替换 '0' 表示 '#if/#elif'
警告 C4668:“bar”未定义为预处理器 宏,用 '0' 代替 '#if/#elif'
所以VALUE 的值是“0”(foo 的默认值)并且bar 也有“0”,所以VALUE == bar 的计算结果为“TRUE”。
同样,clang-cl 给出以下内容:
警告:'foo' 未定义,计算结果为 0 [-Wundef]
警告 : 'bar' 未定义,计算结果为 0 [-Wundef]
【讨论】:
MSVC 和clang-cl 编译器,也可以禁用此警告(特别是,或通过设置适当的警告“级别”)。
要完成你所追求的,试试这个:
#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 中关于防御性编程的章节“代码完成”。
【讨论】: