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

根据C ++的“03标准2.3 / 1:

在进行任何其他处理之前,每个出现三个字符(“三字母序列”)的以下序列之一被表1中指示的单个字符replace。

---------------------------------------------------------------------------- | trigraph | replacement | trigraph | replacement | trigraph | replacement | ---------------------------------------------------------------------------- | ??= | # | ??( | [ | ??< | { | | ??/ | \ | ??) | ] | ??> | } | | ??' | ˆ | ??! | | | ??- | ˜ | ---------------------------------------------------------------------------- 

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

我的问题是使用trigraphs的目的是什么? 使用trigraphs有没有实际的好处?

UPD :在回答中提到一些欧洲键盘没有所有的标点符号,所以非美国的程序员不得不在日常生活中使用三字母符号?

UPD2 :Visual Studio 2010默认情况下closures了三字母支持。

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

归结起来,ISO 646字符集没有C语法的所有字符,所以有一些键盘和显示器不能处理字符的系统(尽pipe我想象这些是非常罕见的如今)。

一般来说,你不需要使用它们,但是你需要知道你遇到的问题。 三angular图是“ ? '字符有一个转义序列:

 '\?' 

所以有几种方法可以避免你的例子问题:

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

但是当你input两个'?'时你必须记得 字符,你可能会开始trigraph(这当然不是我想的东西)。

在实践中,trigraphs和digraphs是我根本不用担心的一个日常的事情。 但是你应该知道它们,因为每过几年你就会遇到一个与它们相关的错误(你将在今天剩下的时间内诅咒它们的存在)。 如果编译器能够configuration为在出现三字母或二元字形时发出警告(或错误),那么这样会很好,所以我可以知道我有一些我应该明确地处理的内容。

只是为了完整性,有向图的危险性要小得多,所以string内的有向图不会被解释为有向图。

对于在C / C ++程序中使用标点符号的各种有趣的教育(包括一个trigraph bug,这个bug会让我把头发拉出来),请看Herb Sutter的GOTW#86文章 。


附录:

它看起来像GCC默认情况下不会处理(并警告)trigraphs。 其他一些编译器可以selectclosurestrigraph支持(例如IBM)。 微软开始支持VS2008中的一个警告(C4837),必须显式启用(使用-Wall或其他)。

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

ASCII特殊字符[]{}| ,并且占据由ISO指定为字母的字符集位置。 在大多数欧洲国家的ISO-646字符集中,这些位置被英文字母中没有的字母占据。

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

孩子们今天! 🙂

是的,外国设备,如IBM 3270terminal。 如果我记得,3270有没有花括号! 如果您想在IBM mini / mainframe上编写C语言,则必须为每个块边界使用可怜的三字母。 幸运的是,我只需要用 C编写软件来模拟一些IBM小型计算机设备,而不是在System / 36 编写C软件。

看旁边的“P”键: http : keyboard/temp/1389260-big.jpg

嗯。 很难说。 “回车”旁边有一个额外的button,我可能会倒退:也许这是缺less的“[”/“]”对。 无论如何,如果你不得不写C,这个键盘会让你感到悲伤。

此外,这些terminal显示EBCDIC,IBM的“本地”大型机字符集,而不是ASCII(谢谢Pavel Minaev提醒)。

另一方面,就像GNU C指南所说:“你不需要这个脑损伤。” gcc编译器将这个“function”默认禁用。

它们适用于缺lessC ++基本字符集中某些字符的系统。 不用说,这样的系统是非常罕见的。

已经提出在C ++ 0x中删除三字格。 也就是说,似乎还有强大的支持它们的论据 – 参见讨论这个的C ++委员会论文N2910 。 显然,EBCDIC是他们所需要的一个主要据点。

我在90年代初见过使用trigraphs来帮助将PL / 1程序从大型机转换到在PC上运行/编译/debugging。

他们正在使用PL / I到C编译器在PC上编辑PL / I,他们希望代码在移回到不支持大括号的大型机上工作。 我build议他们可以使用macros

 #def BEGIN { #def END } 

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

 #def BEGIN ??< #def END ??> 

如果他们真的想成为他们可以尝试

 #ifdef MAINFRAME #def BEGIN ??< #def END ??> #else #def BEGIN { #def END } #endif 

然后程序会看起来像是在帕斯卡尔写的。 他们只是看着我好笑,在今天剩下的时间里都不会跟我说话。 我不认为我责怪他们。 🙂

什么不是三图什么杀,这是平台之间的IO系统差异。 在PC上打开文件和主机有很大不同,它会引入太多的工具来保持相同的代码在两者上运行。

一些欧洲的键盘没有(没有?)拥有美国键盘所有的标点字符,因为他们需要键盘来处理不寻常的字母字符。 所以举个例子(做这个),瑞典的键盘上会有A形环,大括号就是这个。

为了适应这些用户,trigraphs是只使用最常见的ASCII字符input标点符号的一种方法。

主要是因为C标准在1989年介绍过它们,当时在某些机器上出现了三字符映射的字符存在问题。 到1998年C ++标准出版时,对trigraphs的需求并不是很大。 他们是C的疣; 它们在C ++上就像一个疣一样。 他们需要 – 特别是在说英语的世界之外 – 这就是为什么他们被添加到C.

他们大多是因为历史原因。 如今,绝大多数语言的大多数现代键盘都允许访问所有这些字符,但这曾经是一些欧洲键盘的问题。 这就是为什么三撇子是被发明的。

如果你不知道他们是为了什么,你不应该使用它们。

尽pipe如此,还是很好的意识到它们,因为你可能会偶然和无意中在你的代码中使用一个。