提问人:Peter Olson 提问时间:10/20/2011 最后编辑:Peter Olson 更新时间:8/19/2021 访问量:391576
??!??!有什么作用运算符在 C 中做什么?
What does the ??!??! operator do in C?
问:
我看到一行 C 看起来像这样:
!ErrorHasOccured() ??!??! HandleError();
它编译正确,似乎运行正常。它似乎正在检查是否发生了错误,如果发生了错误,它会处理它。但我真的不确定它到底在做什么,或者它是如何做到的。看起来程序员确实在试图表达他们对错误的感受。
我以前从未在任何编程语言中看到过它,我在任何地方都找不到它的文档。(谷歌对这样的搜索词没有帮助)。它有什么作用,代码示例是如何工作的???!??!
??!??!
答:
??!
是一个三字法,翻译为 .所以它说:|
!ErrorHasOccured() || HandleError();
由于短路,相当于:
if (ErrorHasOccured())
HandleError();
本周大师(涉及 C++,但与此处相关),我在那里捡起了这个。
三元组的可能起源,或者正如@DwB在评论中指出的那样,这更有可能是由于 EBCDIC (再次)很困难。IBM developerworks 板上的这个讨论似乎支持了这一理论。
摘自 ISO/IEC 9899:1999 §5.2.1.1,脚注 12 (h/t @Random832):
三元组序列允许输入未在固定代码集中定义为 在 ISO/IEC 646 中描述,它是 7 位美国 ASCII 代码集的子集。
评论
ErrorHasOccurred() && HandleError();
这是一个 C 三元组。 是,运算符也是如此??!
|
??!??!
||
评论
<iso646.h>
好吧,为什么它通常存在可能与它存在于您的示例中的原因不同。
这一切都始于半个世纪前,当时将硬拷贝通信终端重新用作计算机用户界面。在最初的 Unix 和 C 时代,那是 ASR-33 电传打字机。
这个设备很慢(10 cps),嘈杂和丑陋,它对ASCII字符集的视图在0x5f结束,所以它(仔细看图片)没有键:
{ | } ~
定义三元组是为了解决特定问题。这个想法是,C程序可以使用ASR-33和其他环境中缺少高ASCII值的ASCII子集。
您的示例实际上是
??!
中的两个,每个都表示|
,因此结果是||
。
然而,几乎从定义上讲,编写 C 代码的人拥有现代设备,1 所以我的猜测是:有人炫耀或自娱自乐,在代码中留下一种复活节彩蛋供你寻找。
它确实奏效了,它导致了一个广受欢迎的 SO 问题。
ASR-33 电传打字机
1. 就此而言,三元组是由 ANSI 委员会发明的,该委员会在 C 取得巨大成功后首次开会,因此没有一个原始的 C 代码或编码人员会使用它们。
评论
#
£
if (x || y) { a[i] = '\0'; }
if (x öö y) ä aÄiÅ = 'Ö0'; å
如前所述,本质上是两个三元组(再次)混在一起,它们被预处理器替换-转换为,即逻辑 OR。??!??!
??!
??!
||
下表包含每个三元组,应有助于消除备用三元组组合的歧义:
Trigraph Replaces
??( [
??) ]
??< {
??> }
??/ \
??' ^
??= #
??! |
??- ~
资料来源:C:参考手册第 5 版
因此,一个看起来像的三元组最终会映射到 ,将被替换为 等等,你就明白了。??(??)
[]
??(??)??(??)
[][]
由于三元组在预处理过程中被替换,因此您可以使用cpp
自己获取输出视图,使用一个愚蠢的程序:trigr.c
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 没有提供英语以外的其他语言所需的字符数量,因此制作了一些国家变体,用需要的字符替换一些较少使用的字符。
(强调我的)
因此,从本质上讲,某些需要的字符(存在三元组的字符)在某些国家变体中被替换。这导致使用由其他变体仍然存在的字符组成的三叉形的替代表示。
评论
char *date = "??-??-??!"
char *date = "~~|";
)
if(data??(x??)??(y??)=='??/r' ??!??! data??(x??)??(y??)==0) ??< break; ??>
?:
评论