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

时间:2009-08-05 17:15:40

标签: c++ c++03 trigraphs

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

  

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

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

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

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

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

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

9 个答案:

答案 0 :(得分:89)

This question (about the closely related digraphs)有答案。

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

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

'\?'

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

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

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

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

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

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

要想在C / C ++程序中使用标点符号进行各种有趣的教育(包括一个可以让我把头发拉出来的三字母错误),请查看Herb Sutter's GOTW #86 article


附录:

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

答案 1 :(得分:20)

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

  

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

     

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

答案 2 :(得分:18)

今天的孩子们! : - )

是的,外国设备,如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编译器默认禁用此“功能”。

答案 3 :(得分:13)

它们适用于缺少C ++基本字符集中某些字符的系统。毋庸置疑,这种系统非常罕见。

答案 4 :(得分:8)

已经建议在C ++ 0x中删除Trigraph。也就是说,支持它们似乎仍有很强的论据 - 参见C ++委员会文件N2910,讨论了这一点。显然,EBCDIC是需要它们的一个主要据点。

答案 5 :(得分:4)

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

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

这样的宏
#def BEGIN {    
#def END }  

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

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

如果他们真的想得到幻想他们可以尝试

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

然后程序看起来像是用Pascal编写的。他们只是看着我好笑,并且不会在一天的剩余时间里跟我说话。我不认为我责备他们。 :)

什么杀死了这些努力,而不是三图,这是平台之间的IO系统差异。在PC上打开文件与大型机有很大的不同,它会引入太多的kludges来保持相同的代码在两者上运行。

答案 6 :(得分:3)

某些欧洲键盘没有(没有?)具有美国键盘所具有的所有标点字符,因为它们需要键盘来显示其不寻常的字母字符。所以例如(这样做),瑞典键盘将有一个大括号的A形环。

为了适应这些用户,三字母是一种仅使用最常见的ASCII字符输入标点符号的方法。

答案 7 :(得分:2)

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

如果您不知道它们的用途,则不应使用它们。

但是,知道它们仍然很好,因为你可能会在你的代码中意外地和无意地使用它们。

答案 8 :(得分:2)

主要是因为C标准在1989年引入了它们,当时在某些机器上存在三字符映射到的字符存在问题。当C ++标准于1998年发布时,对三字母的需求并不大。他们是C的疣;它们与C ++一样多。他们需要 - 特别是在英语世界之外 - 这就是为什么他们被添加到C。