提问
我看到一行C看起来像这样:
!ErrorHasOccured() ??!??! HandleError();
它编译正确,似乎运行正常。看起来它正在检查是否发生了错误,如果有错误,它会处理它。但我不确定它实际在做什么或它是如何做的。看起来程序员正试图表达他们对错误的看法。
我以前从未在任何编程语言中看过
??!??!
,而且我无法在任何地方找到它的文档。(Google对??!??!
等搜索术语没有帮助)。它做了什么以及代码示例如何工作?最佳参考
??!
是一个翻译为|
的三字母。所以它说:[32]!ErrorHasOccured() || HandleError();
由于短路,相当于:
if (ErrorHasOccured())
HandleError();
本周的大师(处理C ++,但在这里相关),我选择了这一点。[33]
三角形的可能起源或@DwB在评论中指出它更可能是由于EBCDIC很难(再次)。这个关于IBM developerworks董事会的讨论似乎支持这一理论。[34] [35]
来自ISO/IEC 9899:1999§5.2.1.1,脚注12(h/t @ Random832):
??三字符序列允许输入未在不变代码集中定义的字符
??在ISO/IEC 646中描述,它是7位US ASCII码集的子集。
其它参考1
那么,为什么这一般存在可能与你的例子中存在的原因不同。
这一切都始于半个世纪前,将硬拷贝通信终端重新用作计算机用户界面。在最初的Unix和C时代,那是ASR-33电传打字机。
这个设备很慢(10 cps),噪音和丑陋,它的ASCII字符集视图以0x5f结束,因此它(仔细观察图片)没有任何键:
{ | } ~
定义三字母以解决特定问题。我们的想法是,C程序可以使用ASR-33上的ASCII子集以及缺少高ASCII值的其他环境。[36]
??你的例子实际上是??!
中的两个,每个都意味着|
,所以结果是||
。
然而,几乎按定义编写C代码的人有现代设备, 1 所以我的猜测是:某人炫耀或自娱自乐,在代码中留下一种复活节彩蛋你找到了。
它确实有效,它导致了一个广受欢迎的SO问题。
                       &NBSP ;???????????????????? ASR-33 Teletype
1。就此而言,三角形是由ANSI委员会发明的,该委员会在 C成功失败后首次遇到,因此原始的C代码或编码器都不会使用它们。
其它参考3
正如已经陈述的那样
??!??!
本质上是两个三字母(??!
和??!
再次合并而被替换 - 被翻译为||
,即<强预>逻辑OR ,由预处理器完成。 [39] [40]包含所有三字母的下图将有助于消除替代三字母组合的歧义:
(图片取自 C:A参考手册第5版) [41] [42]
所以看起来像
??(??)
的三元组最终将映射到[]
,??(??)??(??)
将被[][]
取代,依此类推,你得到了这个想法。由于在预处理过程中替换了三字符,你可以使用
cpp
自己查看输出,使用愚蠢的trigr.c
程序:[43]void main(){ const char *s = "??!??!"; }
并处理它:
cpp -trigraphs trigr.c
你将得到一个控制台输出
void main(){ const char *s = "||"; }
您可以注意到,必须指定选项
-trigraphs
,否则cpp
将发出警告;这表明三字母是如何成为过去的事物,除了让可能碰到它们的人感到困惑之外没有现代价值。至于引入三元组背后的基本原理,在查看
ISO/IEC 646
的历史部分时可以更好地理解:[44]
??ISO/IEC 646及其前身ASCII(ANSI X3.4)在很大程度上支持了有关电信行业字符编码的现有做法。
??
??由于ASCII没有提供除英语以外的语言所需的许多字符,制作了许多国家变体,用一些较少使用的字符替换了所需的字符 。
(强调我的)
因此,从本质上讲,某些所需的角色(存在三角形的角色)在某些国家变体中被替换。这导致使用由其他变体仍然存在的字符组成的三字符的替代表示。
强预>