[英]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 中所述,這是七位美國 ASCII 代碼集的子集。
那么,為什么這通常存在可能與它在您的示例中存在的原因不同。
這一切都始於半個世紀前,將硬拷貝通信終端重新用作計算機用戶界面。 在最初的 Unix 和 C 時代,即 ASR-33 電傳打字機。
這個設備很慢(10 cps)、嘈雜和丑陋,它對 ASCII 字符集的看法以 0x5f 結束,所以它(仔細看圖片)沒有任何鍵:
{ | } ~
三合字母被定義為解決特定問題。 這個想法是 C 程序可以使用在 ASR-33 和其他環境中發現的 ASCII 子集,但缺少高 ASCII 值。
你的例子實際上是兩個
??!
, 每個意思|
,所以結果是||
.
然而,幾乎按照定義,編寫 C 代碼的人都有現代設備, 1所以我的猜測是:有人炫耀或自娛自樂,在代碼中留下一種復活節彩蛋供您找到。
它確實有效,它導致了一個廣受歡迎的 SO 問題。
ASR-33 電傳打字機
這是一個 C三合字母。 ??!
是|
,所以??!??!
是運算符||
如前所述??!??!
本質上是兩個 三合字母( ??!
和??!
再次)混合在一起,被替換翻譯為||
,即邏輯 OR ,由預處理器執行。
包含每個三合字母的下表應該有助於消除替代三合字母組合的歧義:
Trigraph Replaces
??( [
??) ]
??< {
??> }
??/ \
??' ^
??= #
??! |
??- ~
來源: C:參考手冊第 5 版
所以看起來像??(??)
的三合字母最終會映射到[]
, ??(??)??(??)
將被替換為[][]
等等,你明白了。
由於在預處理期間替換了trigr.c
字母,您可以使用cpp
自己查看輸出,使用一個愚蠢的trigr.c
程序:
void main(){ const char *s = "??!??!"; }
並用以下方法處理它:
cpp -trigraphs trigr.c
你會得到一個控制台輸出
void main(){ const char *s = "||"; }
如您-trigraphs
必須指定選項-trigraphs
,否則cpp
將發出警告; 這表明三合字母已成為過去,除了混淆可能會碰到它們的人之外,沒有任何現代價值。
至於引入三字符背后的基本原理,在查看ISO/IEC 646 的歷史部分時會更好地理解:
ISO/IEC 646 及其前身 ASCII (ANSI X3.4) 在很大程度上認可了電信行業中有關字符編碼的現有實踐。
由於 ASCII 沒有提供除英語之外的其他語言所需的大量字符,因此制作了許多國家變體,用所需的字符替換了一些較少使用的字符。
(強調我的)
因此,本質上,某些國家變體中替換了一些需要的字符(存在三合字母的字符)。 這導致使用由其他變體仍然存在的字符組成的三合字母的替代表示。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.