2013-07-18 43 views
21

我正在重構一些非常舊遺留代碼,它充滿了錯誤和非常可疑的實踐,至少對於現代標準來說。現在,我在一行跑,我根本無法破譯:神祕線「??!??!」在遺留代碼

pk是類型int *

return p??!??!k?p?*p:sizeof(*k):0; 

當我看到它,我簡直不敢相信自己的眼睛 - 我知道?運營商,但它的語法是bool ? trueresult : falseresult??操作符都沒有意義(懶惰評估確實不適用於此),我無法在任何地方找到該神祕運算符的參考。

如果有人在這個問題上有所瞭解,這將是非常酷的。

+2

http://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C – qrdl

+0

哪個編譯您使用?例如,gcc默認忽略三字母符號。是的,這確實是*非常非常古老的代碼。 – devnull

+0

@devnull它是gcc,但它是用Makefile編譯的。現在我知道什麼是三字母了,我也知道爲什麼有一個傳遞給編譯器的'-trigraphs'標誌;) – user2573221

回答

37

這就是所謂的Trigraph

C11(ISO/IEC 9899:201X)§5.2.1.1三字母序列

任何其他處理髮生之前,以下 之一每次出現三個字符的序列(稱爲三字母序列17))被相應的單個字符替換爲 。

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

它也是在C++ 11(ISO/IEC 14882:2011)§2.3 三字符序列

所以三字符替換之後,行return p??!??!k?p?*p:sizeof(*k):0;變成

return p || k ? p ? *p : sizeof(*k) : 0 

由於三元算子的優先級較低,實際上它是:

return (p || k) ? (p ? (*p) : sizeof(*k)) : 0; 
6

這行代碼就相當於:

return p || k? p? *p : sizeof(*k) : 0; 

或者更明確:

return (p || k)? (p? (*p) : sizeof(*k)) : 0;