Zweck von Trigraph-Sequenzen in C ++?

127

Gemäß C ++ '03 Standard 2.3 / 1:

Bevor eine andere Verarbeitung stattfindet, wird jedes Auftreten einer der folgenden Sequenzen von drei Zeichen ("Trigraphsequenzen") durch das in Tabelle 1 angegebene Einzelzeichen ersetzt.

----------------------------------------------------------------------------
| trigraph | replacement | trigraph | replacement | trigraph | replacement |
----------------------------------------------------------------------------
| ??=      | #           | ??(      | [           | ??<      | {           |
| ??/      | \           | ??)      | ]           | ??>      | }           |
| ??’      | ˆ           | ??!      | |           | ??-      | ˜           |
----------------------------------------------------------------------------

Im wirklichen Leben bedeutet dies, dass Code zum printf( "What??!\n" );Drucken führt, What|da ??!es sich um eine Trigraphsequenz handelt, die durch das |Zeichen ersetzt wird.

Meine Frage ist, welchen Zweck die Verwendung von Trigraphen hat. Gibt es einen praktischen Vorteil bei der Verwendung von Trigraphen?

UPD : In den Antworten wurde erwähnt, dass einige europäische Tastaturen nicht alle Satzzeichen haben, so dass Nicht-US-Programmierer im Alltag Trigraphen verwenden müssen.

UPD2 : In Visual Studio 2010 ist die Trigraph-Unterstützung standardmäßig deaktiviert .

Kirill V. Lyadvinsky
quelle
Ein Teil der Interpunktion ist auf europäischen Tastaturen schwerer zu erreichen (bis zu dem Punkt, dass einige Programmierer das US-Layout verwenden, um schneller zu tippen). Haben Sie noch keinen gesehen, bei dem die Interpunktion vollständig fehlt - vielleicht für slawische Sprachen?
Peterchen
2
Es kann vorkommen, dass Sie mit einigen Terminals und / oder Virtualisierungen nicht einfach auf einige Zeichen zugreifen können. Nach meiner Erfahrung ist der Haupttäter die Tilde.
Francesco
1
Wenn Sie dies auf meiner DE-Deadkeys-Tastatur eingeben, ist # eine Taste neben der Rückgabe, \ ist "AltGr" + "ß" (neben 0), ^ ist "^" + "^" (wegen Deadkeys; neben 1) , [ist "AltGr" + "8",] ist "AltGr" + "9", | ist "AltGr" + "<", {ist "AltGr" + "7",} ist "AltGr" + "0" und ~ ist "~" + "~" (wegen Deadkeys direkt über #). also keine wirklich große Sache. Meine Finger sind wie das Tippen dieser Kombinationen für sich :-D
Nonchip
1
Ich dachte, dass es normal ist, zwei Tastaturlayouts zu haben und sie entsprechend der Arbeit, die ich am Computer mache, zu wechseln. Dies ist der übliche Weg in der Region Mitteleuropa. Es ist ziemlich gruselig, diese Trigraphen zu benutzen. Ich würde dafür stimmen, dies aus dem Standard zu entfernen.
VX
1
@VX Du hast deinen Wunsch!
Graham.reeds

Antworten:

97

Diese Frage (über die eng verwandten Digraphen) hat die Antwort.

Es läuft darauf hinaus, dass der ISO 646-Zeichensatz nicht alle Zeichen der C-Syntax enthält. Daher gibt es einige Systeme mit Tastaturen und Anzeigen, die mit den Zeichen nicht umgehen können (obwohl ich mir vorstelle, dass diese recht selten sind heutzutage).

Im Allgemeinen müssen Sie sie nicht verwenden, aber Sie müssen sie genau kennen, um das Problem zu lösen, auf das Sie gestoßen sind. Trigraphen sind der Grund, warum das ?Zeichen ' ' eine Escape-Sequenz hat:

'\?'

So können Sie Ihr Beispielproblem auf folgende Weise vermeiden:

 printf( "What?\?!\n" ); 

 printf( "What?" "?!\n" ); 

Aber Sie müssen sich daran erinnern, wenn Sie die beiden '?' Zeichen, mit denen Sie möglicherweise einen Trigraph beginnen (und an die ich sicherlich nie denke).

In der Praxis sind Trigraphen und Digraphen etwas, worüber ich mir im Alltag überhaupt keine Sorgen mache. Aber Sie sollten sich ihrer bewusst sein, denn alle paar Jahre werden Sie auf einen Fehler stoßen, der mit ihnen zusammenhängt (und Sie werden den Rest des Tages damit verbringen, ihre Existenz zu verfluchen). Es wäre schön, wenn Compiler so konfiguriert werden könnten, dass sie warnen (oder Fehler verursachen), wenn sie auf einen Trigraph oder Digraph stoßen, damit ich weiß, dass ich etwas habe, mit dem ich mich wissentlich befassen sollte.

Und der Vollständigkeit halber sind Digraphen viel weniger gefährlich, da sie als Token verarbeitet werden, sodass ein Digraph in einem String-Literal nicht als Digraph interpretiert wird.

Werfen Sie einen Blick auf Herb Sutters GOTW # 86-Artikel , um eine gute Einführung in verschiedene Themen mit Interpunktion in C / C ++ - Programmen zu erhalten (einschließlich eines Trigraph-Fehlers, der mich definitiv dazu bringen würde, mir die Haare auszureißen) .


Nachtrag:

Es sieht so aus, als würde GCC Trigraphen standardmäßig nicht verarbeiten (und davor warnen). Einige andere Compiler haben Optionen zum Deaktivieren der Trigraph-Unterstützung (z. B. IBMs). Microsoft hat damit begonnen, eine Warnung (C4837) in VS2008 zu unterstützen, die explizit aktiviert werden muss (mithilfe von -Wall oder Ähnlichem).

Michael Burr
quelle
Kompatibilität mit C ist der einzige Grund? Ist das möglich, sie in modernen C ++ - Programmen zu treffen?
Kirill V. Lyadvinsky
Ja, C ++ unterstützt auch Trigraphen und Digraphen.
Michael Burr
4
Soweit ich mich erinnere, benötigt mindestens ein von mir verwendeter Compiler (g ++?) Eine explizite Befehlszeilenoption, bevor Trigraph und / oder Digraph übersetzt werden. Andernfalls wird eine Warnung ausgegeben, jedoch keine Ersetzung.
KTC
1
@ Jla3ep - Ich persönlich hatte noch nie einen Bedarf an Trigraphen, aber leider verarbeiten Compiler Code mit ihnen, daher müssen Sie sich dessen bewusst sein (um eine versehentliche Verwendung zu vermeiden). Wenn Sie Code von einem anderen Ort erhalten, kann dies zu einer absichtlichen Verwendung führen. Dies wäre jedoch äußerst ungewöhnlich. Ich glaube, ich bin in über 20 Jahren einmal auf absichtlich verwendete Trigraphen gestoßen (es war ein Code für einen IBM-Mainframe).
Michael Burr
1
Es geht mir wirklich nur auf die Nerven, wenn Trigraphen in Kommentaren erweitert werden, um überraschende Dinge zu tun.
Joshua
23

Kinder heute! :-)

Ja, ausländische Geräte wie ein IBM 3270-Terminal. Der 3270 hat, wenn ich mich recht erinnere, keine geschweiften Klammern! Wenn Sie schreiben C auf einem IBM - mini / Mainframe wollten, Sie mußten die elende trigraphs für jede Blockgrenze verwenden. Glücklicherweise musste ich nur Software in C schreiben, um einige IBM Minicomputer-Funktionen zu emulieren , und keine C-Software auf dem System / 36 schreiben .

Schauen Sie neben der Taste "P" nach:

Tastatur

Hmmm. Schwer zu erzählen. Es gibt einen zusätzlichen Knopf neben "Wagenrücklauf", und ich könnte ihn rückwärts haben: Vielleicht fehlte das Paar "[" / "]". Auf jeden Fall würde diese Tastatur Ihnen Kummer bereiten, wenn Sie C schreiben müssten.

Außerdem zeigen diese Terminals EBCDIC an, den "nativen" Mainframe-Zeichensatz von IBM, nicht ASCII (danke, Pavel Minaev, für die Erinnerung).

Auf der anderen Seite, wie der GNU C-Leitfaden sagt: "Sie brauchen diesen Hirnschaden nicht." Der gcc-Compiler lässt diese "Funktion" standardmäßig deaktiviert.

Roboprog
quelle
1
Auf der Tastatur befindet sich eine Reset-Taste. Das ist großartig! Seltsam, dass meine Aufmerksamkeit zuerst auf sich gezogen hat.
l46kok
10
Wer C ++ 17 auf einem EBCDIC-Computer verwenden möchte, sollte wegen Nekrophilie inhaftiert werden.
SF.
Es sei denn , eine Plattform keine Zeichen hat bei allen anderen als den in ISO646, konnte nicht alles, was mit trigraphs getan werden kann, durch getan werden , zu verlangen , dass jede Implementierung entweder einen Schrägstrich definieren oder auch jedes Zeichen , das nicht in der C - Zeichensatz als a "Meta" -Zeichen, alle Verweise auf Backslash im Standard durch "Meta" ersetzen und Backslash / Meta-Escapezeichen für alle Mitglieder des C-Zeichensatzes hinzufügen, die nicht in ISO-646 enthalten sind?
Supercat
22

Aus der The C++ Programming LanguageSpecial Edition, Seite 829

Die ASCII - Sonderzeichen [, ], {, }, |, und \besetzen Positionen Zeichensatz als alphabetisch nach ISO bezeichnet. In den meisten nationalen europäischen ISO-646-Zeichensätzen sind diese Positionen mit Buchstaben belegt, die im englischen Alphabet nicht enthalten sind.

Es wird ein Satz von Trigraphen bereitgestellt, mit denen nationale Zeichen auf tragbare Weise unter Verwendung eines wirklich standardmäßigen minimalen Zeichensatzes ausgedrückt werden können. Dies kann für den Austausch von Programmen nützlich sein, erleichtert jedoch nicht das Lesen von Programmen. Die langfristige Lösung für dieses Problem besteht natürlich darin, dass C ++ - Programmierer Geräte erhalten, die sowohl ihre Muttersprache als auch C ++ gut unterstützen. Leider scheint dies für einige nicht realisierbar zu sein, und die Einführung neuer Geräte kann ein frustrierend langsamer Prozess sein.

rauben
quelle
7
"Die Einführung neuer Geräte kann ein frustrierend langsamer Prozess sein". Besonders im Vergleich zu dem schnellen und schmerzlosen Prozess der Standardisierung von Programmiersprachenfunktionen.
Jforberg
4
Wenn dies ein Kludge für Tastaturlayouts ist, dann ist es lustig, dass es keinen Trigraph gibt, z. B. zum Tippen `, der im italienischen und mehreren anderen Tastaturlayouts fehlt
badp
15

Sie sind für Systeme vorgesehen, denen einige der Zeichen im grundlegenden Zeichensatz von C ++ fehlen. Selbstverständlich sind solche Systeme äußerst selten.

CB Bailey
quelle
2
Bedeutet das, dass ich sie niemals im wirklichen Leben verwenden werde?
Kirill V. Lyadvinsky
1
In welchem ​​Land lebst du? Nicht alle Tastaturen für alle Sprachen verfügen über die erforderlichen Tasten.
David Thornley
2
Ja, aber Sie müssen sich möglicherweise dessen bewusst sein, dass es ein unerwartetes Ergebnis gibt, wenn Sie beispielsweise in ein Zeichenfolgenliteral stoßen.
CB Bailey
4
@ David Thornley: Die meisten modernen Systeme unterstützen alle Grundzeichen von C ++, auch wenn sie sich nicht an der herkömmlichen Stelle befinden oder eine Modifikatorsequenz zum Eingeben erfordern. Trigraphen mussten nur im Quellcode auf Systemen gepflegt werden, auf denen das Zeichen im Systemzeichensatz nicht dargestellt werden kann. Ich behaupte immer noch, dass solche Systeme äußerst selten sind.
CB Bailey
9

Trigraphen wurden zum Entfernen in C ++ 0x vorgeschlagen. Trotzdem scheint es immer noch starke Argumente dafür zu geben - siehe C ++ - Ausschusspapier N2910, in dem dies erörtert wird. Anscheinend ist EBCDIC eine wichtige Hochburg, in der sie gebraucht werden.

Pavel Minaev
quelle
Ja, diese "Fremdsprache"! :-)
Roboprog
Sie sagen nicht wirklich viel außer "Ergebnisse einer internen Umfrage zum Kundenfeedback", aber na ja. Ich bin überrascht, dass EBCDIC immer noch weit verbreitet ist (und dass diese Systeme
voraussichtlich
5

Ich habe Trigraphs gesehen, die in den frühen 90ern verwendet wurden, um PL / 1-Programme von einem Mainframe zu konvertieren, der auf einem PC ausgeführt / kompiliert / debuggt werden soll.

Sie beschäftigten sich mit der Bearbeitung von PL / I auf dem PC mit einem PL / I-zu-C-Compiler und wollten, dass der Code funktioniert, wenn er zurück zum Mainframe verschoben wird, der keine geschweiften Klammern unterstützt. Ich schlug vor, dass sie Makros wie verwenden könnten

#def BEGIN {    
#def END }  

oder als freundlichere PL / I-Alternative

#def BEGIN ??<
#def END ??>

und wenn sie wirklich Lust haben wollten, konnten sie es versuchen

#ifdef MAINFRAME
    #def BEGIN ??<
    #def END ??>
#else
    #def BEGIN {    
    #def END }  
#endif

und dann würde das Programm so aussehen, als wäre es in Pascal geschrieben worden. Sie sahen mich nur lustig an und sprachen für den Rest des Tages nicht mit mir. Ich glaube nicht, dass ich ihnen die Schuld gebe. :) :)

Was die Mühe tötete, was nicht die Tri-Graphen, waren die Unterschiede im E / A-System zwischen den Plattformen. Das Öffnen von Dateien auf dem PC war so anders als der Mainframe, dass viel zu viele Kludges eingeführt worden wären, um auf beiden den gleichen Code laufen zu lassen.

Kelly S. Französisch
quelle
PL / 1 = IBMs Version von C (mehr oder weniger). Siehe meinen Kommentar: IBM Terminals haben keine '{' / '}' Schlüssel :-( Ansonsten ist es schwierig, C [++] auf einem dieser Schlüssel zu schreiben.
Roboprog
3

In erster Linie, weil der C-Standard sie 1989 einführte, als es Probleme mit dem Vorhandensein der Zeichen gab, denen Trigraphs auf einigen Maschinen zugeordnet sind. Zum Zeitpunkt der Veröffentlichung des C ++ - Standards im Jahr 1998 war der Bedarf an Trigraphen nicht groß. Sie sind eine Warze auf C; Sie sind genauso eine Warze in C ++. Sie wurden benötigt - insbesondere außerhalb der englischsprachigen Welt - weshalb sie zu C. hinzugefügt wurden.

Jonathan Leffler
quelle
1
Ich habe immer vermutet, dass IBM kein Englisch spricht :-)
Roboprog
3

Einige europäische Tastaturen haben nicht alle Interpunktionszeichen, die US-Tastaturen hatten (nicht?), Weil sie die Tasten für ihre ungewöhnlichen alphabetischen Zeichen benötigten. So hätte zum Beispiel die schwedische Tastatur einen A-Ring, wo sich die geschweifte Klammer befand.

Um diesen Benutzern gerecht zu werden, können Trigraphen die Interpunktion nur mit den gängigsten ASCII-Zeichen eingeben.

Ned Batchelder
quelle
4
Bei Trigraphen geht es nicht wirklich um Dateneingabe (sie machen Code ziemlich unlesbar), sondern eher um Systeme, die nicht die erforderlichen Zeichen haben. Wenn ein System das Zeichen aufzeichnen und anzeigen kann - selbst wenn eine trigraphähnliche Tastenfolge eingegeben werden muss -, ist es viel einfacher, die Trigraphsequenz nicht in der Quelle beizubehalten.
CB Bailey
2

Sie sind meist aus historischen Gründen dort. Heutzutage ermöglichen die meisten modernen Tastaturen für die meisten Sprachen den Zugriff auf all diese Zeichen, aber dies war früher bei einigen europäischen Tastaturen ein Problem. Deshalb wurden Trigraphen erfunden.

Wenn Sie nicht wissen, wofür sie sind, sollten Sie sie nicht verwenden.

Es ist jedoch immer noch gut, sich ihrer bewusst zu sein, da Sie möglicherweise versehentlich und unbeabsichtigt eine in Ihrem Code verwenden.

sbi
quelle