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如此,还是很好的意识到它们,因为你可能会偶然和无意中在你的代码中使用一个。