我看到一行C,看起来像这样:
!ErrorHasOccured() ??!??! HandleError();
它编译正确,运行正常。它似乎在检查是否发生了错误,如果发生了,它会处理它。但我不太确定它实际上在做什么,或者它是如何做的。看起来程序员确实在表达他们对错误的感觉。
我从未见过??!??!我在任何地方都找不到它的文档。(谷歌对搜索词如????!?!没有帮助)。它做什么以及代码示例如何工作?
我看到一行C,看起来像这样:
!ErrorHasOccured() ??!??! HandleError();
它编译正确,运行正常。它似乎在检查是否发生了错误,如果发生了,它会处理它。但我不太确定它实际上在做什么,或者它是如何做的。看起来程序员确实在表达他们对错误的感觉。
我从未见过??!??!我在任何地方都找不到它的文档。(谷歌对搜索词如????!?!没有帮助)。它做什么以及代码示例如何工作?
当前回答
好吧,一般来说,这可能与你的例子中的原因不同。
这一切始于半个世纪前,将硬拷贝通信终端重新用作计算机用户界面。在最初的Unix和C时代,这就是ASR-33 Teletype。
该设备速度慢(10 cps),噪音大,外观难看,ASCII字符集的视图以0x5f结尾,因此(仔细看图片)没有任何键:
{ | } ~
三角图的定义是为了解决特定的问题。其想法是C程序可以使用ASR-33和其他缺少高ASCII值的环境中的ASCII子集。
你的例子实际上是??!,每个都表示|,所以结果是|。
然而,根据定义,编写C代码的人几乎都拥有现代化的设备,因此我的猜测是:有人在炫耀或逗乐自己,在代码中留下一种复活节彩蛋,让你找到。
它确实奏效了,这导致了一个非常流行的SO问题。
ASR-33电传打字机为此,三角图是由ANSI委员会发明的,该委员会在C获得巨大成功后首次开会,因此没有一个原始的C代码或代码编写者会使用它们。
其他回答
好吧,一般来说,这可能与你的例子中的原因不同。
这一切始于半个世纪前,将硬拷贝通信终端重新用作计算机用户界面。在最初的Unix和C时代,这就是ASR-33 Teletype。
该设备速度慢(10 cps),噪音大,外观难看,ASCII字符集的视图以0x5f结尾,因此(仔细看图片)没有任何键:
{ | } ~
三角图的定义是为了解决特定的问题。其想法是C程序可以使用ASR-33和其他缺少高ASCII值的环境中的ASCII子集。
你的例子实际上是??!,每个都表示|,所以结果是|。
然而,根据定义,编写C代码的人几乎都拥有现代化的设备,因此我的猜测是:有人在炫耀或逗乐自己,在代码中留下一种复活节彩蛋,让你找到。
它确实奏效了,这导致了一个非常流行的SO问题。
ASR-33电传打字机为此,三角图是由ANSI委员会发明的,该委员会在C获得巨大成功后首次开会,因此没有一个原始的C代码或代码编写者会使用它们。
这是一个C三角图??!是|,所以??!??!是接线员吗||
??! 是一个转换为|的三元组。所以上面写着:
!ErrorHasOccured() || HandleError();
由于短路,等效于:
if (ErrorHasOccured())
HandleError();
本周大师(与C++有关,但与此相关),我在这里学到了这一点。
可能是trigraphs的起源,或者正如@DwB在评论中指出的那样,更可能是因为EBCDIC很难(再次)。IBM开发人员委员会上的讨论似乎支持这一理论。
根据ISO/IEC 9899:1999§5.2.1.1,脚注12(h/t@Random832):
三角图序列允许输入未在“不变代码集”中定义为其是七位US ASCII码集的子集。
如前所述??!??!本质上是两个三元组(??!和??!)混合在一起,被替换后被预处理器转换为||,即逻辑OR。
包含每个三元图的下表应有助于消除备选三元图组合的歧义:
Trigraph Replaces
??( [
??) ]
??< {
??> }
??/ \
??' ^
??= #
??! |
??- ~
来源:C:A参考手册第5版
那么一个看起来像的三角图??(??)最终将映射到[]??(??)??(??)将被[][]等替换,你明白了。
由于在预处理过程中替换了trigraphs,所以您可以使用一个愚蠢的trigr.c程序,使用cpp自己获取输出的视图:
void main(){ const char *s = "??!??!"; }
并用以下方法进行处理:
cpp -trigraphs trigr.c
您将获得控制台输出
void main(){ const char *s = "||"; }
正如您所注意到的,必须指定选项-trigraphs,否则cpp将发出警告;这表明三角图已成为过去,除了让可能碰到它们的人感到困惑之外,没有任何现代价值。
至于引入三角图背后的基本原理,在查看ISO/IEC 646的历史部分时,可以更好地理解:
ISO/IEC 646及其前身ASCII(ANSI X3.4)在很大程度上认可了电信行业中有关字符编码的现有实践。由于ASCII没有为英语以外的语言提供所需的字符数量,因此产生了一些国家变体,用所需字符替换了一些较少使用的字符。
(强调矿井)
因此,从本质上讲,某些必要的字符(存在三角图的字符)在某些国家变体中被替换。这导致使用由其他变体仍然存在的字符组成的三角图的替代表示。