C + + 中三角图序列的目的? ?

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

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

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

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

我的问题是使用触发器的目的是什么? 使用触发器有什么实际的好处吗?

UPD : 在回答中提到,一些欧洲键盘没有所有的标点符号,所以非美国程序员必须在日常生活中使用触发器?

UPD2 : VisualStudio2010默认关闭了对触发器的支持。

49972 次浏览

它们适用于缺少 C + + 基本字符集中某些字符的系统。不用说,这样的系统是极其罕见的。

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

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

提供了一组触发器,以便使用真正标准的最小字符集以可移植的方式表示国家字符。这对于程序的交换是有用的,但是它不能使人们更容易地阅读程序。当然,这个问题的长期解决方案是让 C + + 程序员获得能够很好地支持他们的本地语言和 C + + 的设备。不幸的是,这对一些人来说似乎是不可行的,并且引进新设备可能是一个令人沮丧的缓慢过程。

一些欧洲键盘没有(不是吗?)有所有的标点符号,美国键盘有,因为他们需要的钥匙,为他们不寻常的字母字符。例如(编造) ,瑞典的键盘在花括号所在的位置有一个 A 形环。

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

他们在那里主要是出于历史原因。如今,大多数语言的现代键盘都允许访问所有这些字符,但这曾经是一些欧洲键盘的问题。这就是发明触发器的原因。

如果你不知道它们的用途,你就不应该使用它们。

尽管如此,注意到它们仍然是件好事,因为您可能会在代码中意外或无意地使用它们。

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

归根结底,ISO 646字符集没有 C 语法中的所有字符,所以有些带键盘和显示器的系统无法处理这些字符(尽管我想现在这样的系统很少)。

通常,您不需要使用它们,但是您需要确切地了解遇到的问题。三角形是‘ ?’字符具有转义序列的原因:

'\?'

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

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


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

但是你必须记住什么时候你在输入两个’你可能会开始一个触发器(当然这绝不是我想的东西)。

在实践中,三角形和有向图是我一点也不担心的东西,在日常的基础上。但是你应该意识到它们的存在,因为每隔几年你就会遇到一个与它们相关的 bug (然后你会在剩下的时间里诅咒它们的存在)。如果能将编译器配置为在遇到触发器或有向图时发出警告(或出错) ,那就太好了,这样我就可以知道我得到了一些我应该知道要处理的东西。

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

对于 C/C + + 程序中各种有趣的标点符号(包括一个绝对会让我抓狂的触发器错误)的良好教育,看看 Herb Sutter 的 GOTW # 86文章


Addendum:

看起来 GCC 在默认情况下不会处理(并会发出警告)触发器。其他一些编译器有关闭触发支持的选项(例如 IBM)。微软开始在 VS2008中支持必须显式启用的警告(C4837)(使用-Wall 或其他方式)。

主要是因为 C 标准早在1989年就引入了它们,当时在一些机器上存在与触发器映射到的字符有关的问题。到1998年 C + + 标准发布的时候,对三叉图的需求还不是很大。它们是 C 上的一个疣; 它们同样也是 C + + 上的一个疣。他们需要它们——特别是在英语世界之外——这就是为什么它们被添加到 c 语言中。

我见过90年代早期用于帮助将 PL/1程序从大型机转换为在 PC 上运行/编译/调试的触发器。

他们正在尝试使用 PL/I to 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

然后程序看起来就像是用帕斯卡写的。他们只是奇怪地看着我然后一整天都不跟我说话。我不怪他们。:)

是什么扼杀了这些努力,而不是三图,而是平台之间 IO 系统的差异。在 PC 上打开文件与在大型机上打开文件有很大的不同,因此会引入太多的软件包,以至于无法在两者上运行相同的代码。

现在的孩子! : -)

是的,国外的设备,例如 IBM 3270终端。如果我没记错的话,3270没有卷曲的牙套!如果您想在 IBM mini/main 上编写 C 语言,那么 必须的对每个块边界都使用可怜的三角形。幸运的是,我只需要用 C 编写软件到 效仿一些 IBM 小型计算机设施,而不是实际编写 C 软件到 System/36。

看“ P”键旁边:

keyboard

嗯。很难说。在“回车”旁边有一个额外的按钮,我可能把它反过来了: 也许是“[”/“]”对不见了。无论如何,如果你不得不写 C 的话,这个键盘会给你带来麻烦。

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

另一方面,正如 GNU C 指南所说: “你不需要这种大脑损伤。”Gcc 编译器默认禁用这个“特性”。

在 C + + 0x 中已经提出了删除三角形的建议。尽管如此,似乎仍然有强有力的论据支持他们-见 C + + 委员会的文件 N2910讨论这一点。显然,EBCDIC 是需要它们的一个主要据点。