多行表达式:c 编译器如何处理换行符?

Multiline expression: How does c compilers treat newline?

提问人:Icelightz 提问时间:8/24/2023 最后编辑:David RanieriIcelightz 更新时间:8/24/2023 访问量:93

问:

我正在阅读 K&R 书中关于 C 的介绍部分。为了查看哪种代码格式会产生错误,我尝试拆分为不同的行,如下所示。问题是,我不知道我的结果是否与实现无关。我使用了 GCC 编译器。printf("hello world!");

C 标准对多行表达式有什么看法?编译器如何处理它们?

/*
    printf("hello wor
    ld!\n");
*/

/*
    printf("hello world!
    \n");
*/

    printf("hello world!\
    n");

/*
    printf("hello world!\n
    ");
*/

    printf("hello world!\n"
    );

    printf("hello world!\n")
    ;

注释掉的表达式会生成错误,而其余表达式不会。

第三个表达式的行为是出乎意料的。通常需要在同一行上终止,但第三个表达式有效。"

第三个表达式:

    printf("hello world!\
    n");

输出到控制台:

hello world!    n

似乎可以用来将字符串拆分为多行,但前面的空格作为字符串的一部分包含在内。这是标准规则吗?\n");

C 分体 式格式 标准 多行

评论

1赞 Retired Ninja 8/24/2023
如果 \ 是一行上的最后一个字符(后面没有空格),则将其视为继续字符。它通常用于宏。多行预处理器宏
1赞 Jonathan Leffler 8/24/2023
请注意,GCC 无论好坏(最坏的是 IMO),都放宽了尾部反斜杠后空格的规则——参见扩展:转义换行符的稍微宽松的规则。这似乎无法通过命令行选项进行控制,尽管 或 的某种组合可能会将警告转换为错误。-Werror-pedantic-pedantic-errors

答:

1赞 Jason 8/24/2023 #1

任何两个连续的字符串文本都将合并。因此,这是完全有效的 C:

printf("hello world!\n"
    ""
    ""
    "next line\n"
);

...或在多行中显示单行:

printf("h" "e"
    "llo " 
    "world!\n"
);

评论

2赞 Jonathan Leffler 8/24/2023
字符串连接不是预处理器函数,它是由编译器在预处理器完成后完成的。请参阅 §5.1.1.2 转换阶段 — 字符串连接是第 6 阶段,但预处理在第 4 阶段结束时完成。
1赞 Jason 8/24/2023
呵呵 [lanuguage-lawyer] 正在泄漏 =]
0赞 Lundin 8/24/2023
@JonathanLeffler 预处理指令(在第 4 阶段)实际上是在字符串连接之前执行的。但迂腐地讲,5.1.1.2“经过预处理,预处理翻译单元称为翻译单元”。这发生在第 7 阶段。字符串文字连接发生在第 6 阶段。“预处理器”的结束位置有点模糊,但我认为说字符串连接不是作为预处理的一部分完成的是正确的。像这样的实现可能会吐出,也可能不会吐出是另一回事。gcc -E
5赞 dave 8/24/2023 #2

C 2018 5.1.1.2

118 2.紧跟换行符的反斜杠字符 (\) 的每个实例都将被删除,从而拼接物理源行以形成逻辑源行。

所以基本上是写

    printf("hello world!\
    n");

与写作相同

    printf("hello world!    n");
2赞 Vlad from Moscow 8/24/2023 #3

编译器将以换行符结尾的每个逻辑行拆分为标记。'\n'

编译器发出错误,例如,对于此代码片段

printf("hello wor
ld!\n");

因为在每条逻辑行(对应于一条或多条物理行)中,都有不正确的标记和"hello world!\n"

您可以通过在换行符之前放置符号来将这两条物理行组合成一条逻辑行,例如'\'

printf("hello wor\
ld!\n");

第二行物理行应从位置 0 开始,以形成字符串文字。"hello world!"

此外,在将行拆分为标记后,编译器会连接相邻的字符串文本标记。因此,您可以写,例如

printf("hello " "world!\n");

printf("hello wor"
"ld!\n");

评论

0赞 Eric Postpischil 8/24/2023
句子“编译器拆分每个逻辑行......在解释“代币”之前,对学生来说“是没有意义的。