C语言 什么??!?!运算符在 C 中做什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7825055/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:56:13  来源:igfitidea点击:

What does the ??!??! operator do in C?

coperatorstrigraphs

提问by Peter Olson

I saw a line of C that looked like this:

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

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

It compiled correctly and seems to run ok. It seems like it's checking if an error has occurred, and if it has, it handles it. But I'm not really sure what it's actually doing or how it's doing it. It does look like the programmer is trying express their feelings about errors.

它编译正确,似乎运行正常。看起来它正在检查是否发生了错误,如果发生了,它会处理它。但我不确定它实际上在做什么或它是如何做的。看起来程序员确实在尝试表达他们对错误的感受。

I have never seen the ??!??!before in any programming language, and I can't find documentation for it anywhere. (Google doesn't help with search terms like ??!??!). What does it do and how does the code sample work?

我以前从未??!??!在任何编程语言中见过它,而且我在任何地方都找不到它的文档。(谷歌不帮助搜索词,如??!??!)。它有什么作用以及代码示例如何工作?

采纳答案by user786653

??!is a trigraphthat translates to |. So it says:

??!是一个三字符是转换为|。所以它说:

!ErrorHasOccured() || HandleError();

which, due to short circuiting, is equivalent to:

由于短路,这相当于:

if (ErrorHasOccured())
    HandleError();

Guru of the Week(deals with C++ but relevant here), where I picked this up.

本周的大师(处理 C++,但在这里相关),我在那里捡到了这个。

Possible origin of trigraphsor as @DwB points out in the comments it's more likely due to EBCDIC being difficult (again). Thisdiscussion on the IBM developerworks board seems to support that theory.

三合字母的可能起源或正如@DwB 在评论中指出的那样,更有可能是因为 EBCDIC 很困难(再次)。在IBM developerWorks板的讨论似乎支持这一理论。

From ISO/IEC 9899:1999 §5.2.1.1, footnote 12 (h/t @Random832):

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

The trigraph sequences enable the input of characters that are not defined in the Invariant Code Set as described in ISO/IEC 646, which is a subset of the seven-bit US ASCII code set.

三字符序列允许输入未在 ISO/IEC 646 中描述的不变代码集中定义的字符,ISO/IEC 646 是七位美国 ASCII 代码集的子集。

回答by DigitalRoss

Well, why this exists in general is probably different than why it exists in your example.

那么,为什么这通常存在可能与它在您的示例中存在的原因不同。

It all started half a century ago with repurposing hardcopy communication terminals as computer user interfaces. In the initial Unix and C era that was the ASR-33 Teletype.

这一切都始于半个世纪前,将硬拷贝通信终端重新用作计算机用户界面。在最初的 Unix 和 C 时代,即 ASR-33 电传打字机。

This device was slow (10 cps) and noisy and ugly and its view of the ASCII character set ended at 0x5f, so it had (look closely at the pic) none of the keys:

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

{ | } ~ 

The trigraphswere defined to fix a specific problem. The idea was that C programs could use the ASCII subset found on the ASR-33 and in other environments missing the high ASCII values.

三合字母被定义为解决特定问题。这个想法是 C 程序可以使用在 ASR-33 和其他环境中发现的 ASCII 子集,但缺少高 ASCII 值。

Your example is actually two of ??!, each meaning |, so the result is ||.

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

However, people writing C code almost by definition had modern equipment,1so my guess is: someone showing off or amusing themself,leaving a kind of Easter egg in the code for you to find.

然而,几乎按照定义,编写 C 代码的人都有现代设备,1所以我的猜测是:有人炫耀或自娱自乐,在代码中留下一种复活节彩蛋供您找到。

It sure worked, it led to a wildly popular SO question.

它确实有效,它导致了一个广受欢迎的 SO 问题。

ASR-33 Teletype

ASR-33 电传打字机

                                            ASR-33 Teletype

                                            ASR-33 电传打字机



1. For that matter, the trigraphs were invented by the ANSI committee, which first met afterC become a runaway success, so none of the original C code or coders would have used them.1. 就此而言,三合字母是由 ANSI 委员会发明的,该委员会C 取得巨大成功首次见面,因此原始 C 代码或编码人员都不会使用它们。

回答by Joel Falcou

It's a C trigraph. ??!is |, so ??!??!is the operator ||

这是一个 C三合字母??!|??!??!运算符也是||

回答by Dimitris Fasarakis Hilliard

As already stated ??!??!is essentially two trigraphs(??!and ??!again) mushed together that get replaced-translated to ||, i.e the logical OR, by the preprocessor.

如前所述??!??!实际上是两个三合??!??!再次)捣成泥在一起会被替换,翻译成||,即逻辑或,由预处理器。

The following table containing every trigraph should help disambiguate alternate trigraph combinations:

包含每个三合字母的下表应该有助于消除替代三合字母组合的歧义:

Trigraph   Replaces

??(        [
??)        ]
??<        {
??>        }
??/        \
??'        ^
??=        #
??!        |
??-        ~

Source: C: A Reference Manual 5th Edition

来源:C:参考手册第 5 版

So a trigraph that looks like ??(??)will eventually map to [], ??(??)??(??)will get replaced by [][]and so on, you get the idea.

所以看起来像的三合字母??(??)最终会映射到[]??(??)??(??)将被替换为[][]等等,你明白了。

Since trigraphs are substituted during preprocessing you could use cppto get a view of the output yourself, using a silly trigr.cprogram:

由于在预处理期间替换了三合字母,您可以使用cpp一个愚蠢的trigr.c程序来自己查看输出:

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

and processing it with:

并用以下方法处理它:

cpp -trigraphs trigr.c 

You'll get a console output of

你会得到一个控制台输出

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

As you can notice, the option -trigraphsmust be specified or else cppwill issue a warning; this indicates how trigraphs are a thing of the past and of no modern value other than confusing people who might bump into them.

如您所见,-trigraphs必须指定该选项,否则cpp将发出警告;这表明三合字母已成为过去,除了混淆可能会碰到它们的人之外,没有任何现代价值



As for the rationale behind the introduction of trigraphs, it is better understood when looking at the history section of ISO/IEC 646:

至于引入三字符背后的基本原理,在查看ISO/IEC 646 的历史部分时会更好地理解:

ISO/IEC 646 and its predecessor ASCII (ANSI X3.4) largely endorsed existing practice regarding character encodings in the telecommunications industry.

As ASCII did not provide a number of characters needed for languages other than English, a number of national variants were made that substituted some less-used characters with needed ones.

ISO/IEC 646 及其前身 ASCII (ANSI X3.4) 在很大程度上认可了电信行业中有关字符编码的现有实践。

由于 ASCII 没有提供除英语之外的其他语言所需的大量字符,因此制作了许多国家变体,用所需的字符替换了一些较少使用的字符

(emphasis mine)

(强调我的)

So, in essence, some needed characters (those for which a trigraph exists) were replaced in certain national variants. This leads to the alternate representation using trigraphs comprised of characters that other variants still had around.

因此,本质上,某些国家变体中替换了一些需要的字符(存在三合字母的字符)。这导致使用由其他变体仍然存在的字符组成的三合字母的替代表示。