Was bedeutet das ??!??! Betreiber tun in C?

Lesezeit: 7 Minuten

Benutzeravatar von Peter Olson
Peter Olsen

Ich sah eine Zeile von C, die so aussah:

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

Es wurde korrekt kompiliert und scheint ok zu laufen. Es scheint, als würde es prüfen, ob ein Fehler aufgetreten ist, und wenn ja, wird es behandelt. Aber ich bin mir nicht wirklich sicher, was es wirklich tut oder wie es es tut. Es sieht so aus, als ob der Programmierer versucht, seine Gefühle über Fehler auszudrücken.

Ich habe die noch nie gesehen ??!??! zuvor in jeder Programmiersprache, und ich kann nirgendwo Dokumentation dafür finden. (Google hilft nicht bei Suchbegriffen wie ??!??!). Was macht es und wie funktioniert das Codebeispiel?

  • Leider dieses Juwel von einem Programm funktioniert nicht in C++17 und neuer.

    – Phönix

    15. Juli 2018 um 12:40 Uhr

  • Trigraphen werden im ISO C23-Standard entfernt.

    – Keith Thompson

    Vor 2 Tagen

Benutzeravatar von user786653
Benutzer786653

??! ist ein Trigraph das bedeutet übersetzt |. Also heißt es:

!ErrorHasOccured() || HandleError();

was aufgrund von Kurzschlüssen äquivalent ist zu:

if (ErrorHasOccured())
    HandleError();

Guru der Woche (befasst sich mit C ++, ist aber hier relevant), wo ich das aufgegriffen habe.

Mögliche Herkunft von Trigraphen oder wie @DwB in den Kommentaren darauf hinweist, liegt es eher daran, dass EBCDIC (wieder) schwierig ist. Dies Diskussionen im IBM Developerworks Board scheinen diese Theorie zu stützen.

Aus ISO/IEC 9899:1999 §5.2.1.1, Fußnote 12 (h/t @Random832):

Die Trigraph-Folgen ermöglichen die Eingabe von Zeichen, die nicht im unveränderlichen Codesatz definiert sind, wie in ISO/IEC 646 beschrieben, der ein Teilsatz des Sieben-Bit-US-ASCII-Codesatzes ist.

  • Trigraphen wurden ursprünglich benötigt, falls Ihre Tastatur kein ‘|’ hatte. Symbol. Hier ist es entweder der Programmierer, der absichtlich nervt, oder ein bizarres Editor-Feature

    – Martin Beckett

    19. Oktober 2011 um 17:02 Uhr


  • Es ist nicht unbedingt EBCDIC – der Satz von Zeichen, die Trigraphen erfordern, stimmt fast genau mit dem Satz von Zeichen überein, die in ISO-646 (dh den alten “nationalen ASCII”-Standards) nicht unveränderlich sind.

    – Random832

    19. Oktober 2011 um 18:01 Uhr

  • Eine perfekt lesbare Alternative wäre ErrorHasOccurred() && HandleError(); Das heißt, wenn Sie an Shell-Scripting gewöhnt sind. 🙂

    – Yam Marcovic

    24. Oktober 2011 um 15:01 Uhr

  • Beachten Sie nur, dass viele Codierungsstandards die Verwendung von Trigraphen und Digraphen ausdrücklich verbieten und viele Compiler und statische Analysatoren ihre Verwendung kennzeichnen.

    – Luciano

    15. April 2015 um 15:35 Uhr

  • Nicht gültig seit C++17 😐

    – Val ist immer noch bei Monica

    15. Dezember 2018 um 17:12 Uhr

Benutzeravatar von DigitalRoss
DigitalRoss

Nun, warum dies im Allgemeinen existiert, ist wahrscheinlich anders als in Ihrem Beispiel.

Alles begann vor einem halben Jahrhundert damit, gedruckte Kommunikationsterminals als Computerbenutzerschnittstellen umzufunktionieren. In der anfänglichen Unix- und C-Ära war das der ASR-33 Teletype.

Dieses Gerät war langsam (10 cps) und laut und hässlich und seine Ansicht des ASCII-Zeichensatzes endete bei 0x5f, also hatte es (sehen Sie sich das Bild genau an) keinen der Schlüssel:

{ | } ~ 

Die Trigraphen wurden definiert, um ein bestimmtes Problem zu beheben. Die Idee war, dass C-Programme die ASCII-Teilmenge verwenden könnten, die auf dem ASR-33 zu finden ist, und in anderen Umgebungen, denen die hohen ASCII-Werte fehlen.

Ihr Beispiel ist eigentlich zwei von ??!jede Bedeutung |so lautet das Ergebnis ||.

Leute, die C-Code schreiben, hatten jedoch fast per Definition eine moderne Ausrüstung,1 also meine vermutung ist: jemand, der angibt oder sich amüsiert, Hinterlassen Sie eine Art Osterei im Code, das Sie finden können.

Es hat auf jeden Fall funktioniert, es führte zu einer sehr beliebten SO-Frage.

ASR-33 Fernschreiber

ASR-33 Fernschreiber


1. Übrigens wurden die Trigraphen vom ANSI-Komitee erfunden, das zuerst zusammentrat nach C wurde zu einem durchschlagenden Erfolg, sodass keiner der ursprünglichen C-Codes oder Programmierer sie verwendet hätte.

  • Es ist nicht der einzige Fall von fehlenden Zeichen in der Tastatur und im Zeichensatz. Der Commodore 64 dürfte vielen Menschen Ende dreißig und darüber bekannter sein – den angezeigten Zeichensätzen fehlten beide geschweiften Klammern (und wahrscheinlich auch der Balken und die Tilde) – in diesem Fall, weil das „ASCII“ kein ASCII war . In ECMA-6 (fast immer ASCII genannt, aber nicht US-ASCII) gab es 18 regionsspezifische Codes, aber ich weiß nicht, welche Codes das waren. Eines kann ich sicher sagen – im britischen “ASCII”, # wurde durch ersetzt £. In anderen Regionen hatte “ASCII” vielleicht keine geschweiften Klammern usw.

    Benutzer180247

    20. Oktober 2011 um 4:06 Uhr

  • Dem ähnlichen ATASCII-Zeichensatz für Atari-8-Bit-Computer fehlten auch { } sowie ~ und `.

    – dan04

    20. Oktober 2011 um 6:16 Uhr


  • Sehen diese zwei Wikipedia-Artikel. Ich bin gerade alt genug, um mich noch an die Ära der nationalen 7-Bit-Zeichensätze zu erinnern (obwohl ich sicher bin, dass sie immer noch in einigen dunklen, ungepflegten Ecken verweilen), und das Buch, aus dem ich zum ersten Mal C gelernt habe, fand es notwendig, davor zu warnen die Möglichkeit, dass if (x || y) { a[i] = '\0'; } sieht aus wie if (x öö y) ä aÄiÅ = 'Ö0'; å im falschen Zeichensatz.

    – Ilmari Karonen

    20. Oktober 2011 um 13:36 Uhr

  • Ein weiterer interessanter historischer Hinweis ist, dass Unix (das war die große Plattform, auf der C gefahren ist) möglicherweise das erste System von Bedeutung (und vielleicht das erste überhaupt) war, das alphabetische Werte auf Kleinbuchstaben statt auf Großbuchstaben voreingestellt hat. Obwohl ich nicht viele zeitgenössische Systeme mit eigenen Augen gesehen habe, denke ich, dass dies ein echtes Zeichen von Raffinesse war. Abgesehen davon, dass Unix wirklich das einzige anständige Betriebssystem ist, hat Unix auch Ihre Großbuchstaben in Kleinbuchstaben konvertiert und nicht umgekehrt. Die Jungs waren echt cool.

    – DigitalRoss

    26. Oktober 2011 um 2:45 Uhr


  • Lustige Geschichte, die ich Ihnen erzählen muss … Der XL Fortran-Compiler der IBM RS/6000-Workstation wurde aus dem XL C-Compiler entwickelt. In den ersten Veröffentlichungen blieben sie versehentlich in der Trigraph-Verarbeitung, daher gab es einige legitime Fortran-Zeichenfolgen (in einer wörtlichen Zeichenfolge, IIRC), die als C-Trigraphen fehlinterpretiert wurden, was zu einigen interessanten Fehlern führte!

    – Phil Perry

    11. April 2014 um 18:25 Uhr


Benutzeravatar von Joel Falcou
Joel Falkou

Es ist ein C Trigraph. ??! ist |Also ??!??! ist der Betreiber ||

  • Trigraph stammen aus einer Zeit, in der einige Tastaturen nicht alle Tasten hatten, die sie heute haben. Es hilft auch, wenn irgendein Texteditor Sonderzeichen für besondere Dinge reserviert hat. Es ist meistens ein Relikt der Vergangenheit und ein Quizz-Enabler 😉

    – Joel Falkou

    23. März 2017 um 19:45 Uhr

  • Da einige Tastaturen anscheinend kein “|” haben Einige Leute haben also keine andere Wahl, als wiederholt auf die Tastatur zu drücken, bis ein Trigraph erscheint, der ihnen die benötigten Symbole gibt.

    – Eule

    11. Januar 2019 um 18:06 Uhr

  • Und dann ist da noch die <iso646.h> Header-Datei.

    – David R. Tribble

    25. Oktober 2019 um 21:08 Uhr

Benutzeravatar von Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Wie zuvor schon gesagt ??!??! ist im Wesentlichen zwei Trigraphen (??! und ??! wieder) zusammengerührt, die ersetzt-übersetzt werden ||dh die logisches ODERdurch den Präprozessor.

Die folgende Tabelle, die jeden Trigraph enthält, sollte helfen, alternative Trigraph-Kombinationen zu unterscheiden:

Trigraph   Replaces

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

Quelle: C: Ein Referenzhandbuch, 5. Auflage

So sieht ein Trigraph aus ??(??) wird schließlich zuordnen [], ??(??)??(??) wird ersetzt durch [][] und so weiter, Sie bekommen die Idee.

Da Trigraphen während der Vorverarbeitung ersetzt werden, könnten Sie verwenden cpp um sich selbst einen Überblick über die Ausgabe zu verschaffen, verwenden Sie ein silly trigr.c Programm:

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

und weiterverarbeiten mit:

cpp -trigraphs trigr.c 

Sie erhalten eine Konsolenausgabe von

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

Wie Sie sehen können, die Option -trigraphs muss angegeben werden oder sonst cpp wird eine Warnung ausgeben; dies zeigt an, wie Trigraphen gehören der Vergangenheit an und haben keinen modernen Wert, außer dass sie Menschen verwirren, die ihnen begegnen könnten.


Was die Begründung hinter der Einführung von Trigraphen betrifft, wird es besser verstanden, wenn man es sich ansieht den Verlaufsabschnitt von ISO/IEC 646:

ISO/IEC 646 und sein Vorgänger ASCII (ANSI X3.4) unterstützten weitgehend die bestehende Praxis bezüglich Zeichencodierungen in der Telekommunikationsbranche.

Da ASCII eine Reihe von Zeichen, die für andere Sprachen als Englisch benötigt werden, nicht bereitstellte, Es wurde eine Reihe nationaler Varianten erstellt, bei denen einige weniger verwendete Zeichen durch benötigte ersetzt wurden.

(Hervorhebung von mir)

Im Wesentlichen wurden also einige benötigte Zeichen (diejenigen, für die ein Trigraph existiert) in bestimmten nationalen Varianten ersetzt. Dies führt zur alternativen Darstellung unter Verwendung von Trigraphen, die aus Zeichen bestehen, die andere Varianten noch hatten.

1428690cookie-checkWas bedeutet das ??!??! Betreiber tun in C?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy