【问题标题】:Why "foo\\<NEWLINE>bar" becomes "foo\bar" after "gcc -E"?为什么“foo\\<NEWLINE>bar”在“gcc -E”之后变成“foo\bar”?
【发布时间】:2017-01-09 07:59:26
【问题描述】:

参见以下示例:

$ cat foo.c
int main()
{
    char *p = "foo\\
bar";
    return 0;
}
$ gcc -E foo.c
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "foo.c"
int main()
{
    char *p = "foo\bar";

    return 0;
}
$

据我了解,第二个\ 被第一个\ 转义,因此第二个\ 不应与以下&lt;NEWLINE&gt; 组合以形成行延续。

【问题讨论】:

标签: c


【解决方案1】:

ISO/IEC 9899:2011 §5.1.1.2 翻译阶段中的规则非常明确:

  1. 反斜杠字符 (\) 的每个实例紧跟一个换行符 字符被删除,拼接物理源行以形成逻辑源行。 只有任何物理源行上的最后一个反斜杠才有资格成为一部分 这样的拼接。

不参考最后一个反斜杠之前的字符。阶段 1 将三元组转换为常规字符。这很重要,因为??/\ 的三元组。

【讨论】:

    【解决方案2】:

    预处理器在尝试标记输入之前删除所有出现的反斜杠换行符;没有逃脱机制。它也不限于字符串文字:

    #inclu\
    de <st\
    dio.h>
    
    int m\
    ain(void) {
        /\
    * yes, this is a comment */
        put\
    s("Hello,\
     world!");
        return 0;
    }
    

    这是有效的代码。

    使用\\ 获取单个\ 仅适用于字符串和字符文字,并且在处理过程中发生得更晚。

    【讨论】:

    • 可能值得注意的是,将这一步放在所有其他步骤之前,可以机械地翻译包含长行的代码,以便在最大行长度太短而无法容纳它的系统上使用,而无需翻译实用程序必须检查源文件中除换行符之外的任何内容(尽管在将文件从使用固定长度记录的系统翻译到具有较短记录长度的系统时,代码需要确保它只添加换行符如果原始行的内容超过了新的最大值)。
    猜你喜欢
    • 1970-01-01
    • 2017-06-23
    • 2022-11-04
    • 2020-10-03
    • 1970-01-01
    • 2014-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多