是否始终在预处理器之前处理注释?

时间:2010-01-05 22:17:37

标签: c comments c-preprocessor

/*
#define FOO
*/

#ifdef FOO
#define BAR "pirate"
#else
#define BAR "ninja"
#endif

int main() { printf(BAR); getchar(); }

在此代码中未定义FOO(Visual Studio 2008)。我假设首先处理注释,然后是预处理器,然后是代码。是否始终在预处理器之前处理注释?这是标准的一部分吗?

6 个答案:

答案 0 :(得分:10)

根据C标准,在程序的翻译(编译)期间有8个翻译阶段。每个注释在转换阶段3中由空白字符替换,而预处理指令在阶段4中执行。

答案 1 :(得分:9)

  

我假设首先处理注释,然后是预处理器,然后是代码。是否始终在预处理器之前处理注释?

排序 - 部分预处理程序的作业 以删除注释。在这种情况下,它并不关心你在评论中有指令;它仍然像其他任何评论一样被删除。

答案 2 :(得分:7)

是的,预处理器在处理指令之前替换了注释。

从C99标准的第5.1.1.2节(翻译阶段):

  

3)源文件被分解为预处理标记和空白字符序列(包括注释)....每个注释被一个空格字符替换....

     

4)执行预处理指令,扩展宏调用,....

答案 3 :(得分:4)

是的,从语言标准的角度来看,在预处理器开始工作之前,会处理注释(替换为空格)

在实际实现中,注释的处理可以通过处理预处理器指令并执行宏替换的相同代码(例如,相同的可执行文件)来完成,但结果必须相同:注释对预处理器本身没有影响。 / p>

在较旧的和/或非标准的代码中,有时可能会看到一些依赖于涉及特定于实现的注释与预处理器关系的非标准行为的技巧,例如,使用预处理器指令创建注释

#define CONCAT(a, b) a##b
#define BEGIN_COMMENT CONCAT(/, *)
#define END_COMMENT CONCAT(*, /)

BEGIN_COMMENT
  This code is supposedly commented-out
END_COMMENT

或使用注释进行预处理程序级别连接(在宏定义中使用不支持##运算符的C编译器)

#define OLD_CONCAT(a, b) a/**/b

这些技巧在标准C中都不合法。它们都不起作用。

答案 4 :(得分:3)

一些快速研究表明,注释会被预处理器转换为 的空白区域。所以,它都是同一流程的一部分。

根据Wikipedia,注释在预处理器指令之前处理。

答案 5 :(得分:2)

是的(在每个理智的宇宙中)。