为什么在Gnu gcc / g ++中为三字符序列解析字符串文字?

时间:2017-12-20 10:46:40

标签: c++ gcc trigraphs

考虑这个无害的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??)

为什么要为三字符分析字符串文字呢?

其他编译器也这样做吗?

2 个答案:

答案 0 :(得分:5)

Trigraphs在翻译阶段1处理(然而,它们在C ++ 17中被删除)。字符串文字相关处理在后续阶段发生。正如C ++ 14标准指定(n4140)[lex.phases]/1.1

  

翻译语法规则的优先级由   以下阶段。

     
      
  1. 物理源文件字符以实现定义的方式映射到基本源字符集   (引入行尾指标的换行符)if   必要。接受的物理源文件字符集是   实现定义。 Trigraph sequence([lex.trigraph])是   由相应的单字符内部表示替换。   任何源文件字符都不在基本源字符集中   ([lex.charset])被通用字符名称替换   指定那个角色。 (实现可以使用任何内部   编码,只要遇到实际的扩展字符   源文件,以及源中表示的相同扩展字符   file作为通用字符名称(即使用\ uXXXX表示法),   处理相同,除非这个替换被还原   原始字符串文字。)
  2.   

这首先发生了,因为正如你在评论中被告知的那样,三卦所代表的角色也需要打印。

答案 1 :(得分:1)

这种行为继承自C编译器和旧时代,当我们使用仅使用7位的串行终端时(第8位是奇偶校验位)。为了允许具有特殊字符的非英语语言(例如法语中的重音àéèêîïù或西班牙语中的ñ),ISO/IEC 646代码页使用一些ASCII(7位)代码来表示它们。特别是,代码0x23,0x24(ASCII中的#$)0x40(@),0x5B到0x5E([\]^),0x60(`)和0x7B到0x7E({{1} })可以用国家变体 1 代替。

由于它们在C中具有特殊含义,因此只需使用ISO 646的不变部分就可以在源代码中使用三字符替换它们。

出于兼容性原因,只有恐龙仍然记得ISO646和7位代码页的(不太好)时,这一直保持到C ++ 14。

1 例如,使用的法语版本:0x23 {|}~,0x40 £ 0x5B-0x5D à,0x60 °ç§,0x7B- 0x7E µ