C++中Trigraph序列的目的是什么?

Kir*_*sky 119 c++ trigraphs c++03

根据C++'03标准2.3/1:

在进行任何其他处理之前,每个出现的以下三个字符序列之一("三字符序列")被表1中指示的单个字符替换.

----------------------------------------------------------------------------
| trigraph | replacement | trigraph | replacement | trigraph | replacement |
----------------------------------------------------------------------------
| ??=      | #           | ??(      | [           | ??<      | {           |
| ??/      | \           | ??)      | ]           | ??>      | }           |
| ??’      | ˆ           | ??!      | |           | ??-      | ˜           |
----------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

在现实生活中,这意味着代码printf( "What??!\n" );将导致打印,What|因为??!是一个被|字符替换的三字符序列.

我的问题是使用三字母的目的是什么?使用三字母有什么实际优势吗?

UPD:在答案中提到一些欧洲键盘没有所有标点字符,所以非美国程序员必须在日常生活中使用三字母组合?

UPD2:Visual Studio 2010默认情况下关闭了三字母支持.

Mic*_*urr 91

这个问题(关于密切相关的有向图)有答案.

归结为ISO 646字符集没有C语法的所有字符这一事实,因此有些系统的键盘和显示器无法处理字符(尽管我认为这些很少见如今).

一般情况下,您不需要使用它们,但您需要了解它们,以确定您遇到的问题.Trigraphs是' ?'字符具有转义序列的原因:

'\?'
Run Code Online (Sandbox Code Playgroud)

因此,有两种方法可以避免您的示例问题:

 printf( "What?\?!\n" ); 

 printf( "What?" "?!\n" ); 
Run Code Online (Sandbox Code Playgroud)

但你必须记住当你输入两个'?'时 你可能会开始三角形的角色(这肯定不是我正在考虑的事情).

在实践中,三元组和有向图是我日常不用担心的事情.但是你应该知道它们,因为每隔几年你就会遇到一个与它们相关的错误(你会花一天的时间来诅咒它们的存在).如果编译器可以被配置为在遇到三字符或有向图时发出警告(或错误),那将是很好的,所以我可以知道我有一些我应该知情处理的东西.

而且为了完整性,有向图的危险性要小得多,因为它们被作为标记处理,所以字符串文字中的有向图不会被解释为有向图.

想要在C/C++程序中使用标点符号进行各种有趣的教育(包括一个可以让我把头发拉出来的三角虫),请看看Herb Sutter的GOTW#86文章.


附录:

看起来GCC默认不会处理(并会警告)三字符.其他一些编译器可以选择关闭三元组支持(例如IBM).Microsoft开始在VS2008中支持警告(C4837),必须明确启用(使用-Wall或其他).

  • 我记得,至少有一个我用过的编译器(g ++?)需要在trigraph和/或digraph被翻译之前使用显式命令行选项,否则会给出警告但没有替换. (3认同)

Rob*_*Rob 20

The C++ Programming Language特别版,第829页

该ASCII特殊字符[,],{,},|,和\占据由ISO指定为字母字符集的位置.在大多数欧洲国家ISO-646字符集中,这些位置由英语字母表中未找到的字母占据.

提供一组三字母以允许使用真正标准的最小字符集以便携方式表达国家字符.这对于程序的交换很有用,但它不会让人们更容易阅读程序.当然,这个问题的长期解决方案是让C++程序员获得支持其母语和C++的设备.不幸的是,这对某些人来说似乎是不可行的,而新设备的引入可能是一个令人沮丧的缓慢过程.

  • "新设备的引入可能是一个令人沮丧的缓慢过程".特别是与标准化编程语言功能的快速且无痛的过程相比. (5认同)
  • 如果这是键盘布局的kludge,那么有趣的是没有三字符例如用于输入`\``,这在意大利语和其他几种键盘布局中都缺失了 (3认同)

Rob*_*rog 20

今天孩子们!:-)

是的,国外设备,如IBM 3270终端.如果我记得的话,3270没有花括号!如果您想在IBM mini/mainframe上编写C,则必须为每个块边界使用不可靠的三字符.幸运的是,我只需要在C中编写软件来模拟一些IBM小型机设备,而不是在System/36 实际编写C软件.

查看"P"键旁边:http: //www.9999hp.net/keyboard/temp/1389260-big.jpg

嗯.很难说."回车"旁边有一个额外的按钮,我可能会倒退:可能是"["/"]"对丢失了.无论如何,如果你不得不写C,这个键盘会让你感到悲伤.

此外,这些终端显示EBCDIC,IBM的"本机"主机字符集,而不是ASCII(感谢Pavel Minaev提醒).

另一方面,就像GNU C指南所说:"你不需要这种脑损伤." gcc编译器默认禁用此"功能".

  • 谁想要在EBCDIC机器上使用C++ 17,谁应该因为恋尸癖而被判入狱. (7认同)
  • 键盘上有一个重置按钮。棒极了!奇怪的是,它首先引起了我的注意。 (2认同)

CB *_*ley 13

它们适用于缺少C++基本字符集中某些字符的系统.不用说,这种系统非常罕见.

  • @David Thornley:大多数现代系统都支持C++的所有基本字符,即使它们不在常规位置或需要修改序列来键入.仅需要在系统中的源代码中维护Trigraph,其中字符实际上不能在系统字符集中表示.我仍然认为这种系统非常罕见. (4认同)
  • 这是否意味着我永远不会在现实生活中使用它们? (2认同)
  • 是的,但你可能需要知道存在的情况,以防一个人在一个字符串文字中遇到意外的结果. (2认同)

Pav*_*aev 8

已经提出在C++ 0x中删除Trigraph.也就是说,支持它们似乎仍然存在强烈的争论 - 请参阅C++委员会文件N2910,其中讨论了这一点.显然,EBCDIC是需要它们的一个主要据点.


Kel*_*nch 5

我见过在 90 年代初期使用的三合字母来帮助将 PL/1 程序从大型机转换为在 PC 上运行/编译/调试。

他们正在尝试使用 PL/I 到 C 编译器在 PC 上编辑 PL/I,并且他们希望代码在移回不支持花括号的大型机时能够工作。我建议他们可以使用宏

#def BEGIN {    
#def END }  
Run Code Online (Sandbox Code Playgroud)

或者作为更友好的 PL/I 替代品

#def BEGIN ??<
#def END ??>
Run Code Online (Sandbox Code Playgroud)

如果他们真的想变得花哨,他们可以尝试

#ifdef MAINFRAME
    #def BEGIN ??<
    #def END ??>
#else
    #def BEGIN {    
    #def END }  
#endif
Run Code Online (Sandbox Code Playgroud)

然后程序看起来就像是用 Pascal 编写的。他们只是有趣地看着我,一整天都没有和我说话。我不认为我责怪他们。:)

杀死努力的不是三图,而是平台之间的 IO 系统差异。在 PC 上打开文件与在大型机上有很大不同,它会引入太多的杂物,无法在两者上运行相同的代码。