C 预处理器:行继续:为什么在反斜杠字符('\')之后不允许完全注释?

Pav*_*kin 3 c comments backslash c-preprocessor

有效代码:

#define M xxx\
yyy
Run Code Online (Sandbox Code Playgroud)

无效代码:

#define M xxx\/*comment*/
yyy

#define M xxx\//comment
yyy
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 为什么在反斜杠字符 ( \)后不允许注释?
  2. 标准怎么说?

更新。补充问题:

  1. 要求(为了实现物理源行的拼接)反斜杠字符 ( \) 必须紧跟一个换行符的要求背后的动机/原因/论证是什么?在反斜杠字符 ( \)之后允许注释(或空格)的障碍是什么?

Eri*_*hil 5

仅当反斜杠字符是行中的最后一个字符时,才将行拼接在一起。C 2018 5.1.1.2 指定了翻译 C 程序的阶段。在第 2 阶段:

每个反斜杠字符 () 后面紧跟一个换行符的实例都被删除,拼接物理源代码行以形成逻辑源代码行......

如果注释跟在反斜杠字符之后,则反斜杠字符后面没有换行符,因此不进行拼接。评论在第 3 阶段处理:

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

关于补充的问题:

要求(为了实现物理源行的拼接)反斜杠字符 ( \) 必须紧跟一个换行符的要求背后的动机/原因/论证是什么?在反斜杠字符 ( \)之后允许注释(或空格)的障碍是什么?

编译C程序的最早处理是最简单的。早期的 C 编译器可能已经实现为简单的过滤器层:首先将本地环境字符或文件存储方法转换为简单的字符流,然后将行拼接在一起(可能处理需要长源代码的问题)行,而必须在 80 列穿孔卡片上键入您的源代码),然后注释将被删除,依此类推。

将行尾用反斜杠标记的行拼接在一起很容易;它只需要查看两个字符。相反,如果我们允许注释跟在标记拼接的反斜杠后面,它会变得复杂:

  • 反斜杠后跟注释后跟换行符将被拼接,但反斜杠后跟注释后跟其他源代码则不会。这需要查看可能有很多字符并解析注释分隔符,可能是多个注释。
  • 拼接线的目的之一是允许跨多条线连续长字符串。(这是在 C 中连接相邻字符串之前。)所以"abc\在一条线上和def"另一条线上将拼接在一起,使"abcdef". 虽然我们可能允许在反斜杠后添加注释以连接行,但我们不想在包含"abc\ /*" /*comment*/. 这意味着进行拼接的代码必须是上下文相关的;如果反斜杠出现在带引号的字符串中,则必须区别对待。


zwo*_*wol 5

在删除注释之前处理反斜杠换行实际上是有原因的这与反斜杠换行符被完全删除而不是像注释那样被(虚拟)水平空白替换的原因相同。这是一个荒谬的理由,但却是官方的理由。这样你就可以通过在第 79 列插入反斜杠换行符,将带有长行的 C 代码机械地强制安装到打孔卡上,无论发生什么划分:

\n
static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * st\\\natbuf)\n{\n        static int warncount = 5;\n        struct __old_kernel_stat tmp;\n\n        if (warncount > 0) {\n                warncount--;\n                printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Re\\\ncompile your binary.\\n",\n
Run Code Online (Sandbox Code Playgroud)\n

(这是我的硬盘上发现的第一块 CI,实际上有不适合打孔卡的行)

\n

为了使其按预期工作,反斜杠换行符必须能够分割 a/*或 a */,例如

\n
/* this comment just so happens to be exactly 80 characters wide at the close *\\\n/\n
Run Code Online (Sandbox Code Playgroud)\n

两种方法都不能兼得:如果在处理反斜杠换行符之前删除注释,那么反斜杠换行符就不会影响注释边界;相反,如果要先处理反斜杠换行符,则反斜杠和换行符之间不能出现注释。

\n

(我不是在编这个\xe2\x84\xa2:C99基本原理第5.1.1.2节第30段读取

\n
\n

换行符前面的反斜杠长期以来一直用于继续字符串文字以及预处理命令行。为了简化 C 的机器生成,以及将代码传输到物理行长度受限的机器,C89 委员会推广了这种机制,以允许任何通过插入反斜杠/换行符序列来继续

\n
\n

强调原文。抱歉,我不知道此文档有任何非 PDF 版本。)

\n