【问题标题】:Are comments always processed before the preprocessor? [duplicate]注释总是在预处理器之前处理吗? [复制]
【发布时间】:2011-01-01 20:16:30
【问题描述】:
/*
#define FOO
*/

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

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

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

【问题讨论】:

    标签: c comments c-preprocessor


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我假设首先处理 cmets,然后是预处理器,然后是代码。 cmets 总是在预处理器之前处理吗?

      预处理器工作的一部分删除cmets。在这种情况下,它并不关心您在 cmets 中有指令;它仍然像任何其他评论一样被删除。

      【讨论】:

        【解决方案3】:

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

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

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

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

        【讨论】:

          【解决方案4】:

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

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

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

          #define CONCAT(a, b) a##b
          #define BEGIN_COMMENT CONCAT(/, *)
          #define END_COMMENT CONCAT(*, /)
          
          BEGIN_COMMENT
            This code is supposedly commented-out
          END_COMMENT
          

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

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

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

          【讨论】:

            【解决方案5】:

            一些快速研究表明,cmets 被预处理器转换为空格。所以,这都是同一个流程的一部分。

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

            【讨论】:

              【解决方案6】:

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

              【讨论】:

                猜你喜欢
                • 2023-03-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-12-03
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多