什么C?!??! 运营商呢?

我看到一行C,看起来像这样:

!ErrorHasOccured() ??!??! HandleError(); 

它编译正确,似乎运行良好。 它似乎正在检查是否发生错误,如果有,它会处理它。 但是我不确定它究竟在做什么或者它是如何做的。 看起来程序员正在试图expression他们对错误的感受。

我从来没有见过??!??! 之前在任何编程语言,我无法find任何地方的文档。 (谷歌没有帮助search条件,如??!??! )。 它是做什么的,代码示例如何工作?

??! 是翻译为|的三元组 。 所以它说:

 !ErrorHasOccured() || HandleError(); 

由于短路,相当于:

 if (ErrorHasOccured()) HandleError(); 

本周大师 (处理C ++,但在这里相关),我在这里挑选。

三字母的可能来源或@DwB在评论中指出,由于EBCDIC很难(再次),这可能是由于EBCDIC的原因。 关于IBM developerworks板的讨论似乎支持这一理论。

根据ISO / IEC 9899:1999§5.2.1.1,脚注12(h / t @ Random832):

trigraph序列允许input未在不变代码集中定义的字符,如ISO / IEC 646中所述,它是7位US ASCII代码集的子集。

那么,为什么这一般存在可能不同于为什么它存在于你的例子。

这一切都是在半个世纪前开始的,将硬拷贝通信terminal重新用作计算机用户界面。 在最初的Unix和C时代是ASR-33 Teletype。

这个设备很慢(10 cps),嘈杂和丑陋,它的ASCII字符集的观点结束于0x5f,所以它(仔细看照片)没有任何关键:

 { | } ~ 

trigraphs被定义为解决一个特定的问题。 这个想法是,C程序可以使用在ASR-33上find的ASCII子集,而在其他环境中则缺less高的ASCII值。

你的例子其实是两个??! ,每个含义| ,所以结果是||

但是,编写C代码的人几乎都有现代化的设备,所以我的猜测是: 有人炫耀或者自娱自乐,在代码中留下一种复活节彩蛋供你查找。

它确实工作,这导致了一个广泛stream行的SO问题。

ASR-33电传打字机

ASR-33电传打字机


1.对于这个问题,这个三元组是由ANSI委员会发明的,C委员会 C成为一个失控的成功之后第一次遇到了这个委员会,所以原来的C代码或编码人员都不会使用它们。

这是C 三联 。 ??!| ,所以??!??! 是运营商||

如前所述??!??! 基本上是两个三元组 (又一个三元组 ),一起组合起来,得到replace – 翻译为|| ,即预处理器的逻辑或

以下包含所有三字母符号的图像应该有助于消除其他三字母组合的歧义:

在这里输入图像描述 (从C:A参考手册第5版获取的图像

因此,看起来像??(??)的三angular形将最终映射到[]??(??)??(??)将被replace为[][]等等,您就明白了。

由于trigraphs在预处理过程中被replace,所以可以使用一个愚蠢的trigr.c程序使用cpp自己获得输出的视图:

 void main(){ const char *s = "??!??!"; } 

并处理它:

 cpp -trigraphs trigr.c 

你会得到一个控制台输出

 void main(){ const char *s = "||"; } 

你可以注意到,选项-trigraphs必须指定,否则cpp将发出警告; 这表明三撇子如何是过去的事物,没有现代价值,除了混淆可能碰到他们的人


至于引入三字母的基本原理,在查看ISO/IEC 646History部分时更好理解:

ISO / IEC 646及其前身ASCII(ANSI X3.4)在很大程度上支持电信行业字符编码的现行做法。

由于ASCII没有提供英语以外的语言所需的许多字符,因此制作了许多国家的变体,用一些less用的字符replace了所需的字符

(重点是我的)

所以,本质上,某些需要的字符(三字母存在的字符)被replace为某些国家的变体。 这导致使用由其他变体仍然具有的字符组成的替代表示。