2013-07-18 11 views
21

Jestem refactoring jakiś bardzo stary kod źródłowy, który jest pełen błędów i bardzo wątpliwych praktyk, przynajmniej dla nowoczesnych standardów. Teraz natknąłem jednej linii, która po prostu nie mogę rozszyfrować:Cryptyczna linia "??! ??!" w dotychczasowym kodzie

p i k są typu int *

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

Kiedy zobaczyłem go nie mogłem uwierzyć własnym oczom - Wiem operatora ?, ale jego składnia jest bool ? trueresult : falseresult i operator ?? nie ma sensu (leniwe oceny naprawdę nie mają tu zastosowania), nie mogłem znaleźć odniesienia do tego tajemniczego operatora w dowolnym miejscu.

Byłoby naprawdę fajnie, gdyby ktoś rzucił trochę światła na tę sprawę.

+2

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

+0

Które kompilatora używasz ? gcc na przykład domyślnie ignoruje trigraphy. I tak, to musi być * bardzo, bardzo stary * kod. – devnull

+0

@devnull To gcc, ale jest skompilowany z plikiem Makefile. A teraz, gdy już wiem, czym są trigraphy, również wiem, dlaczego do kompilatora jest przekazywana flaga '-trigraphs';) – user2573221

Odpowiedz

37

Nazywa Trigraph:

C11 (ISO/IEC 9899: 201x) §5.2.1.1 Trigraph sekwencje

Zanim jakiekolwiek inne przetwarzanie odbywa się każde wystąpienie jednego z następujących sekwencje trzech znaków (zwane sekwencjami trigraph17)) zastępuje się odpowiadającym pojedynczym znakiem .

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

To również w C++ 11 (ISO/IEC 14882: 2011) § 2.3 sekwencji Trigraph

Więc po wymianie trigraph linia return p??!??!k?p?*p:sizeof(*k):0; zamienia

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

Ponieważ operator trójskładnikowy ma raczej niski priorytet, w rzeczywistości jest to:

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

To linia kodu jest równoważne:

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

lub więcej wyraźnie:

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