为什么在 Gnu gcc/g++ 中解析三元组序列的字符串文字?
Why are string literals parsed for trigraph sequences in Gnu gcc/g++?
考虑这个无害的C++程序:
#include <iostream>
int main() {
std::cout << "(Is this a trigraph??)" << std::endl;
return 0;
}
当我使用 g++ 版本 5.4.0 编译它时,我得到以下诊断:
me@my-laptop:~/code/C++$ g++ -c test_trigraph.cpp
test_trigraph.cpp:4:36: warning: trigraph ??) ignored, use -trigraphs to enable [-Wtrigraphs]
std::cout << "(Is this a trigraph??)" << std::endl;
^
程序运行,其输出符合预期:
(Is this a trigraph??)
为什么要为三元组解析字符串文字?
其他编译器也这样做吗?
三元组在翻译阶段 1 中处理(但是,它们在 C++17 中删除)。字符串文本相关处理在后续阶段进行。正如 C++14 标准规定的 (n4140) [lex.phases]/1.1:
翻译语法规则中的优先级由下式指定 以下阶段。
物理源文件字符以
- 实现定义的方式映射到基本源字符集 (为行尾指示器引入换行符)if 必要。接受的物理源文件字符集为 实现定义。三元组序列([lex.trigraph])是 替换为相应的单字符内部表示形式。不在基本源字符集中的任何源文件字符 ([lex.charset]) 替换为通用字符名称 指定该字符。(实现可以使用任何内部 编码,只要在 源文件,以及源文件中表示的相同扩展字符 文件作为通用字符名称(即使用 \uXXXX 表示法), 等效处理,除非在 原始字符串文本。
这首先发生,因为正如您在评论中被告知的那样,三字形所代表的字符也需要可打印。
这种行为继承自 C 编译器和旧时代,当时我们使用仅使用 7 位的串行终端(第 8 位是奇偶校验位)。为了允许使用特殊字符的非英语语言(例如法语中的重音àéèêîïôù或西班牙语中的ñ),ISO/IEC 646代码页使用了一些ASCII(7位)代码来表示它们。特别是,代码0x23、0x24(ASCII#$
)0x40(@
)、0x5B至0x5E([]^
)、0x60(')和0x7B至0x7E({|}~
)可以用国家变体1取代。
由于它们在 C 中具有特殊含义,因此可以在源代码中仅使用 ISO 646 的不变部分将它们替换为三元组。
出于兼容性原因,这一直保持到 C++14,当时只有恐龙仍然记得 ISO646 和 7 位代码页的(不太好)时代。
1例如,使用的法语变体:0x23£
、0x40à
0x5B-0x5D°ç§
、0x60µ
、0x7B-0x7Eéùè¨
相关文章:
- 使用 jsoncpp 解析 json 数组字符串
- 如何有效地找到数组中三元组和的最小差异?
- 黑客兰克中的错误比较三元组代码
- 在C++中生成字母的三元组
- C++ 按数值对元组<字符串、浮点数>然后按字典顺序排序的向量
- 如何根据长度然后字母顺序对数组字符串进行排序?
- C++ 对象数组字符串输入在控制台上不起作用
- 插入了 C++ 数组字符串数据,但在显示输出时不显示
- 特征用三元组填充稀疏行主矩阵
- 求数组中三元组 (i, j, k) 的数量,使得 A[i] + A[j] = 2 * A[k]
- C 一组字符串的所有布置
- 无法区分 JSON 对象/数组/字符串
- 为什么数组(字符串类型)的大小是 24 字节,带有单个空格元素
- 如何使用数组字符串进行输入验证
- 从向量<T>创建一组字符串
- 为什么在 Gnu gcc/g++ 中解析三元组序列的字符串文字?
- (C++) 打印字符数组字符串的单词时出现问题
- C 排序无法排序一组字符串
- 使用Back_inserter从任何位置的输入字符中使用Back_inserter进行过滤数组字符串
- C 函数反转字符数组字符串