Pytanie Co robi C ??! ??! operator zrobić?


Widziałem linię C, która wyglądała tak:

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

Jest poprawnie skompilowany i wydaje się działać poprawnie. Wygląda na to, że sprawdza, czy wystąpił błąd, a jeśli tak, to go obsługuje. Ale nie jestem do końca pewien, co właściwie robi i jak to robi. Wygląda na to, że programista próbuje wyrazić swoje uczucia na temat błędów.

Nigdy nie widziałem ??!??! wcześniej w jakimkolwiek języku programowania, i nie mogę znaleźć nigdzie dokumentacji. (Google nie pomaga w wyszukiwaniach takich jak ??!??!). Co robi i jak działa przykład kodu?


1605
2017-10-19 16:56


pochodzenie


wyrażaj swoje emocje w inny sposób, nie używaj trigrafii, pisz kodu, który może być zrozumiany przez ludzi - David Heffernan
@PeterOlson, jak się spodziewasz !ErrorHasOccurred() ??!???! HandleError(); kompilować? Jest to ??!  ???  !. Dowodzi tego? - Michael Kjörling
Sugeruję przeczytanie na czystym kodzie. ErrorHasOccured () powinno być refaktoryzowane do ErrorHasNotOccured (), tym samym czyszcząc wykrzyknik ... kto ma czas, aby zrozumieć wszystkie te operatory?! - KadekM
Wolę raczej ErrorHasOccured() && HandleError() siebie. Tak samo postępuje Lua. - Hugo Zink
@KadekM, przeniesienie negacji do nazwy funkcji nie tworzy czystego kodu, a wręcz przeciwnie. - marcelm


Odpowiedzi:


??! jest trigraf co przekłada się na |. Tak więc mówi:

!ErrorHasOccured() || HandleError();

który, ze względu na zwarcie, jest równoważny z:

if (ErrorHasOccured())
    HandleError();

Guru tygodnia (zajmuje się C ++, ale istotne tutaj), gdzie to wybrałem.

Możliwe pochodzenie trigraphs lub jak @DwB wskazuje na komentarze, jest to bardziej prawdopodobne, ponieważ EBCDIC jest trudny (ponownie). To dyskusja na temat płyty IBM Developerworks wydaje się wspierać tę teorię.

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

Sekwencje trigrafu umożliwiają wprowadzanie znaków, które nie są zdefiniowane w kodzie niezmiennego ustawienia jako   opisany w ISO / IEC 646, który jest podzbiorem siedmiobitowego zestawu kodów US ASCII.


1320
2017-10-19 16:58



Początkowo Trigraphy były potrzebne, gdy klawiatura nie miała np. "|" symbol. Tutaj jest albo programista celowo irytujący, albo jakiś dziwaczny edytor "funkcji" - Martin Beckett
Tak, to odpowiednik if (ErrorHasOccured()) HandleError(). Na szczęście zazwyczaj spotykasz się z tym idiomem w kodzie perl. - user786653
To niekoniecznie EBCDIC - zestaw znaków, które wymagają trigrafów, prawie dokładnie pasuje do zestawu znaków, które nie są niezmienne w ISO-646 (to jest starych "narodowych standardów ascii"). - Random832
Idealna czytelna alternatywa ErrorHasOccurred() && HandleError(); Oznacza to, że jeśli używasz skryptów powłoki. :) - Yam Marcovic
Przeczytaj go jako "albo nie błąd ErrorHasOcurred, albo musisz HandleError", @SparkyRobinson. - Omar Antolín-Camarena


Cóż, to, dlaczego tak jest, jest prawdopodobnie inne niż to, dlaczego istnieje w twoim przykładzie.

Wszystko zaczęło się pół wieku temu dzięki przeformułowaniu twardych terminali komunikacyjnych jako interfejsów użytkownika komputera. W początkowej fazie Unix i C, która była typem ASR-33.

To urządzenie było powolne (10 cps) i hałaśliwe i brzydkie, a jego widok zestawu znaków ASCII zakończył się na 0x5f, więc miał (przyjrzeć się dokładnie picowi) żaden z kluczy:

{ | } ~ 

Trigraphs zostały zdefiniowane w celu rozwiązania określonego problemu. Pomysł polegał na tym, że programy C mogły korzystać z podzbioru ASCII znalezionego w ASR-33 oraz w innych środowiskach pozbawionych wysokich wartości ASCII.

Twój przykład to dwa z nich ??!, każde znaczenie |, więc wynik jest ||.

Jednak ludzie piszący kod C prawie z definicji mieli nowoczesny sprzęt,1 więc zgaduję, że: ktoś popisujący się lub bawiący sobą, zostawiając w kodzie rodzaj jajka wielkanocnego.

Na pewno działało, doprowadziło to do niezwykle popularnego pytania SO.

ASR-33 Teletype

ASR-33 Teletype


1. W tym przypadku trigrafy zostały wymyślone przez komitet ANSI, który po raz pierwszy się spotkał po C stał się niekwestionowanym sukcesem, więc żaden z oryginalnych kodów C ani programistów nie użyłby ich.


355
2017-10-19 21:09



Nie jest to jedyny przypadek braku znaków, klawiatury i zestawu znaków. Commodore 64 jest prawdopodobnie bardziej znany wielu ludziom w późnych latach trzydziestych i wyżej - w wyświetlonym zestawie znaków brakowało nawiasów klamrowych (i prawdopodobnie także paska i tyld) - w tym przypadku, ponieważ "ASCII" nie było ASCII . W ECMA-6 (prawie zawsze nazywanym ASCII, ale nie US-ASCII) było 18 kodów specyficznych dla regionu, ale nie wiem, które to były kody. Jedno mogę powiedzieć na pewno - w brytyjskim "ASCII", #został zastąpiony przez £. W innych regionach może "ASCII" nie ma nawiasów klamrowych itp. - Steve314
Podobny zestaw znaków ATASCII dla 8-bitowych komputerów Atari również nie posiadał {}, a także ~ i. - dan04
Widzieć te  dwa Artykuły z Wikipedii. Jestem wystarczająco stary, by wciąż pamiętać erę 7-bitowych narodowych zestawów znaków (choć jestem pewien, że wciąż trwają w ciemnych, nieskażonych zakątkach), a książka, którą pierwszy raz poznałem w C, uznała za konieczne ostrzec o możliwość if (x || y) { a[i] = '\0'; } wygląda jak if (x öö y) ä aÄiÅ = 'Ö0'; å w niewłaściwym zestawie znaków. - Ilmari Karonen
Inną interesującą historyczną nutą jest to, że Unix (który był dużą platformą na której jeździł C) mógł być pierwszym systemem o dowolnym znaczeniu (i być może pierwszym ogólnym) z domyślnymi wartościami alfabetu dla małych liter, a nie wielkich liter. Chociaż nie widziałem na własne oczy wielu współczesnych systemów, myślę, że to była prawdziwa oznaka wyrafinowania. Poza tym, że naprawdę jest jedynym przyzwoitym systemem operacyjnym, Unix również przekształcił twoje wielkie litery na niższe, zamiast na odwrót. Ci faceci byli naprawdę fajni. - DigitalRoss
Zabawna historia Muszę ci powiedzieć ... Kompilator XL Fortran firmy IBM RS / 6000 został opracowany z kompilatora XL C. W pierwszych kilku wydawnictwach przypadkowo pozostały one w przetwarzaniu trigraficznym, więc istniały pewne legalne sekwencje znaków Fortrana (w ciągu literowym, IIRC), które zostały źle zinterpretowane jako trigraphy C, co prowadzi do kilku interesujących błędów! - Phil Perry


To jest C trigraf. ??! jest |, więc ??!??! jest operatorem ||


140
2017-10-19 16:58



dlaczego ktoś powinien używać? zamiast | ??? / - Fatemeh Karimi
Trigraph pochodzą z okresu, w którym niektóre klawiatury nie miały wszystkich kluczy, które mają teraz. To także hels, gdy jakiś edytor tekstu zarezerwował specjalne znaki dla specjalnych rzeczy. To przeważnie relikt przeszłości i kibicowanie;) - Joel Falcou


Jak już wspomniano ??!??! jest zasadniczo dwa trigraphs (??! i ??! ponownie) wymieszane razem, które zostają zastąpione - przetłumaczone na ||, czyli Logiczna ORprzez preprocesora.

Poniższy obrazek zawierający wszystkie trigraphy powinien pomóc w wyodrębnieniu alternatywnych kombinacji trigraficznych:

enter image description here (Zdjęcie pochodzi z C: A Reference Manual 5. wydanie)

Tak wygląda trigrafia ??(??) w końcu utworzą mapę [], ??(??)??(??) zostanie zastąpiony przez [][] i tak dalej, masz pomysł.

Ponieważ trigraphy są zastępowane podczas preprocesingu, możesz użyć cpp aby uzyskać widok wyników samodzielnie, używając głupiego trigr.c program:

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

i przetwarzanie go za pomocą:

cpp -trigraphs trigr.c 

Otrzymasz wyjście konsoli

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

Jak można zauważyć, opcja -trigraphs musi być określony inaczej cpp wyda ostrzeżenie; to wskazuje, jak trigrafy należą już do przeszłości i nie mają żadnej nowoczesnej wartości, poza myleniem ludzi, którzy mogliby na nie wpaść.


Jeśli chodzi o uzasadnienie wprowadzenia trigraphs, to lepiej zrozumieć, patrząc na Historia Sekcja ISO/IEC 646:

ISO / IEC 646 i jego poprzednik ASCII (ANSI X3.4) w dużej mierze poparły istniejącą praktykę dotyczącą kodowania znaków w branży telekomunikacyjnej.

Ponieważ ASCII nie zapewnia liczby znaków potrzebnych dla języków innych niż angielski, wykonano wiele narodowych wariantów, które zastąpiły niektóre mniej używane postacie potrzebnymi


80
2018-03-25 02:24



⁺¹ dla tabeli innych trigrafów. - Hi-Angel