有向图是由编译器转换的,而三字母由预处理器转换的吗?

Are digraphs transformed by a compiler and trigraphs transformed by a preprocessor?

我试图同时理解三字母和二字母而不是使用它们。

我已阅读 并了解到:

这是真的吗?

二合字母没有“转换为相应的字符”。字符串文字 "<:" 包含两个字符 <:(加上空终止符)。如果你有一个支持三字母的编译器,将它与字符串 "??(" 进行对比。

<: 只是一个标记,与 [ 具有完全相同的句法意义。但它永远不会转换为 [。如果将它传递给 stringify 运算符 #,您将得到字符串 "<:".

在编译过程的第一阶段,在预处理器词法分析器分析字符流以生成预处理器标记之前,三字母序列确实被替换为相应的字符。

紧接着的下一个阶段处理转义的换行符,即:\ 的实例紧跟一个换行符,它们从字符流中删除。 请注意,\ 可以由第一阶段生成,以替代 ??/ 三字母

词法分析器然后分析字符流以生成预处理标记,例如 [<:,它们是同一标记的替代拼写,就像 1e11E1,因此 <: 不是 替换 [,它是产生相同标记的不同字符序列。

三字母不能通过在宏扩展中使用 ## 预处理器运算符粘贴标记来生成,但二字母可以。

这里有一个小示例程序来说明这个过程,包括扩展到 \??/ 三字母的特殊处理,因此可以在 2 上的二字母拆分中间使用行:

#include <stdio.h>

#define STR(x) #x
#define xSTR(x) STR(x)
#define glue(a,b) a##b

int main() {
    puts(STR(??!));
    puts(STR('??!'));
    puts(STR("??!"));

    puts(STR(<:));
    puts(STR('<:'));
    puts(STR("<:"));

    puts(STR(<\
:));
    puts(STR(<??/
:));
    puts(STR('<\
:'));
    puts(STR("<\
:"));

    puts(STR(glue(<,:)));
    puts(xSTR(glue(<,:)));
    return 0;
}

输出:

chqrlie $ make lexing && ./lexing
clang -O3 -funsigned-char -std=c11 -Weverything -Wwrite-strings  -lm -o lexing lexing.c
lexing.c:8:14: warning: trigraph converted to '|' character [-Wtrigraphs]
    puts(STR(??!));
             ^
lexing.c:9:15: warning: trigraph converted to '|' character [-Wtrigraphs]
    puts(STR('??!'));
              ^
lexing.c:10:15: warning: trigraph converted to '|' character [-Wtrigraphs]
    puts(STR("??!"));
              ^
lexing.c:18:15: warning: trigraph converted to '\' character [-Wtrigraphs]
    puts(STR(<??/
              ^
4 warnings generated.
|
'|'
"|"
<:
'<:'
"<:"
<:
<:
'<:'
"<:"
glue(<,:)
<: