为啥 C 预处理器不忽略它跳过的块中的无效指令?
Posted
技术标签:
【中文标题】为啥 C 预处理器不忽略它跳过的块中的无效指令?【英文标题】:Why doesn't the C preprocessor ignore invalid directives in blocks it skips?为什么 C 预处理器不忽略它跳过的块中的无效指令? 【发布时间】:2016-12-25 17:27:36 【问题描述】:考虑以下代码:
#if 0
#foobar
#endif
在这种情况下,预处理器不会抱怨#foobar
不是有效的预处理器指令。由于#if 0
,它只是跳过了该块,并且代码编译得很好。
现在考虑以下代码:
#if 0
#if 1
#endif
在这种情况下,预处理器突然抱怨缺少#endif
指令。这让我很困惑,因为它表明即使在#if 0
的情况下,预处理器似乎也没有完全忽略#if 0
块中的内容。似乎#if
指令仍在被解析,预处理器甚至会强制它们的正确性,即每个#if
都需要与#endif
匹配,即使在被跳过的块中也是如此。
以前,我的印象是使用#if 0
/ #endif
封装一个块相当于使用/*
和*/
对其进行注释。但显然情况并非如此。
因此我的问题是:
这种设计背后的基本原理是什么?为什么预处理器会强制执行正确匹配的 #if
指令,即使是在预处理器被明确告知要跳过的块中(使用 #if 0
等某些指令)?
哪些指令确切在#if 0
块中处理?如上例所示,预处理器不会抱怨像#foobar
这样的无效预处理器指令,但它会抱怨不匹配的#if
指令。那么哪些预处理器指令实际上是在#if 0
块中处理的?只有#if
/ #ifdef
/ #elif
/ #else
/ #endif
还是有更多的指令在#if 0
块中处理?
【问题讨论】:
因为预处理器不知道 which#if
缺少 #endif
。缩进不告诉它!在第二个示例中,如果您缩进 #endif
,错误消息会让您感到惊讶吗?
预处理器必须查看 #if
/#endif
指令,即使在未采用的分支中,否则嵌套的 #if
不可能工作。跨度>
哦,对,当然有道理。很明显为什么它必须是这样的。好吧,我想让我们把它归咎于圣诞节:)
【参考方案1】:
只处理可以改变控制流的指令。其余的,如#foobar
被忽略1。
1(引自:ISO/IEC 9899:201x 6.10.1 有条件包含 6) 按顺序检查每个指令的条件。如果它评估为假(零),则该组 它控制的被跳过:指令仅通过确定的名称来处理 该指令用于跟踪嵌套条件的级别;剩下的 指令的预处理标记被忽略,其他预处理标记也是如此 组
【讨论】:
以上是关于为啥 C 预处理器不忽略它跳过的块中的无效指令?的主要内容,如果未能解决你的问题,请参考以下文章