为什么C预处理器不会忽略它跳过的块中的无效指令?

And*_*eas 2 c c-preprocessor

请考虑以下代码:

#if 0
   #foobar
#endif
Run Code Online (Sandbox Code Playgroud)

在这种情况下,预处理器不会抱怨它#foobar不是有效的预处理器指令.它只是跳过块#if 0而且代码编译得很好.

现在考虑以下代码:

#if 0
   #if 1
#endif
Run Code Online (Sandbox Code Playgroud)

在这种情况下,预处理器突然抱怨说缺少#endif指令.这让我感到困惑,因为它表明,即使在#if 0预处理器的情况下,似乎也没有完全忽略#if 0块中的内容.似乎#if仍然会解析指令,并且预处理器甚至会强制执行它们的正确性,即每个都#if需要匹配#endif,即使在跳过的块中也是如此.

以前,我的印象是使用#if 0/ 封装一个块#endif相当于使用/*和对它进行注释*/.但显然事实并非如此.

因此我的问题:

  1. 这个设计背后的理由是什么?为什么预处理器强制执行正确匹配的#if指令,即使在预处理器被明确告知使用某些指令跳过的块中也是如此#if 0

  2. 哪些指令完全#if 0块处理?如上例所示,预处理器不会抱怨无效的预处理器指令,#foobar但它会抱怨无法匹配的#if指令.那么哪些预处理器指令实际上是用#if 0块处理的?只有#if/ #ifdef/ #elif/ #else/ #endif或者是否有更多的指令在#if 0块中处理?

250*_*501 7

仅处理可能更改控制流的指令.其余的,#foobar都被忽略1.


1(引用自:ISO/IEC 9899:201x 6.10.1条件包含6)
按顺序检查每个指令的条件.如果它的计算结果为false(零),则跳过它控制的组:仅通过确定指令的名称处理指令,以便跟踪嵌套条件的级别; 其他指令的预处理标记将被忽略,组中的其他预处理标记也将被忽略