Ist es obligatorisch, Tabulatorzeichen in C und C++ zu maskieren?

Lesezeit: 6 Minuten

Benutzeravatar von tglas
Glas

In C und C++ (und mehreren anderen Sprachen) werden horizontale Tabulatoren (ASCII-Code 9) in Zeichen- und Stringkonstanten in Escape-Form als bezeichnet '\t' und "\t". Ich tippe jedoch regelmäßig das nicht maskierte Tabulatorzeichen in Zeichenfolgenliterale wie zum Beispiel in "A B" (dazwischen ist ein TAB A und B), und zumindest scheint clang++ nicht zu stören – die Zeichenfolge scheint äquivalent zu sein "A\tB". Mir gefällt die Version ohne Escapezeichen besser, da lange eingerückte mehrzeilige Zeichenfolgen im Quellcode besser lesbar sind.

Jetzt frage ich mich, ob das in C und C++ generell erlaubt ist oder nur von meinem Compiler unterstützt wird. Wie portabel sind Tabulatoren ohne Escapezeichen in Zeichen- und Stringkonstanten?

Überraschenderweise konnte ich auf diese scheinbar einfache Frage keine Antwort finden, weder bei Google noch auf Stackoverflow (ich habe gerade diese vage verwandte Frage gefunden).

  • Hast du deine Editoreinstellungen überprüft? Manchmal wird ein Tabulator automatisch in eine Anzahl von Leerzeichen umgewandelt

    – 463035818_ist_keine_Nummer

    6. März 2015 um 14:31 Uhr

  • Jedes Mal, wenn Sie auf etwas Ähnliches stoßen, stellen sich zwei Fragen: “Können Sie?” und “sollten Sie?”. Und meist ist Letzteres das Wichtigste…

    – Karoly Horvath

    6. März 2015 um 14:41 Uhr


  • @KarolyHorvath: Ich denke, beide sind gleich wichtig, zumindest beim Programmieren. Sie brauchen immer “rechtliches” Wissen und “moralisches” Wissen, um jede Programmiersprache wirklich zu beherrschen.

    – Christian Hackl

    6. März 2015 um 14:58 Uhr

  • @EvdzhanMustafa: nein – dann könntest du verwenden \t irgendwo in deiner Quelle. Diese Syntax ist Spezifisch für Strings und Zeichenliterale nur. Sie denken vielleicht an Trigraphen, die zwischen Quelle und Vorverarbeitung liegen.

    – Jongware

    6. März 2015 um 15:10 Uhr

  • @tobi303 Ich habe den Editor selbst geschrieben, also bin ich mir sicher, dass ein Tab ein Tab ist ein Tab 🙂

    – Glas

    6. März 2015 um 15:22 Uhr

Benutzeravatar von Mike Seymour
Mike Seymour

Ja, Sie können ein Tabulatorzeichen in einen String oder ein Zeichenliteral einfügen, zumindest gemäß C++11. Zu den erlaubten Zeichen gehören (mit meiner Betonung):

jedes Mitglied der Quellzeichensatz außer dem doppelten Anführungszeichen "Backslash \oder Zeilenumbruchzeichen

(aus C++11-StandardAnlage A.2)

und der Quellzeichensatz enthält:

das Leerzeichen, die Steuerzeichen darstellen horizontaler Reitervertikaler Tabulator, Seitenvorschub und Zeilenumbruch sowie die folgenden 91 grafischen Zeichen

(aus C++11-StandardAbsatz 2.3.1)

AKTUALISIEREN: Mir ist gerade aufgefallen, dass Sie nach zwei verschiedenen Sprachen fragen. Für C99 lautet die Antwort ebenfalls ja. Der Wortlaut ist anders, sagt aber im Grunde dasselbe:

In einer Zeichenkonstante oder einem Zeichenfolgenliteral müssen Mitglieder des Ausführungszeichensatzes durch entsprechende Mitglieder von dargestellt werden Quellzeichensatz oder […]

wobei sowohl der Quell- als auch der Ausführungszeichensatz enthalten

Steuerzeichen darstellen horizontaler Reitervertikaler Tabulator und Seitenvorschub.

  • Und auch in rohem String.

    – Jarod42

    6. März 2015 um 15:05 Uhr

  • @ Jarod42: In der Tat kann ein rohes Zeichenfolgenliteral alles aus dem Quellzeichensatz enthalten, abgesehen von der von Ihnen gewählten Trennzeichenfolge.

    – Mike Seymour

    6. März 2015 um 15:10 Uhr

  • Danke für die schnelle Antwort und auch für die Zitate aus dem Standard.

    – Glas

    6. März 2015 um 19:00 Uhr

  • Theoretisch kann also ein String ein nicht maskiertes \0 (dh ein 0x00-Byte in der Quelldatei) enthalten?

    – Andreas Bonini

    7. März 2015 um 10:34 Uhr

  • @AndreasBonini: Nein, das ist kein Mitglied des Quellzeichensatzes.

    – Mike Seymour

    7. März 2015 um 13:23 Uhr

Benutzeravatar von rici
rici

Es ist völlig legal, ein Tabulatorzeichen direkt in eine Zeichenfolge oder ein Zeichenliteral einzufügen. Die C- und C++-Standards verlangen, dass der Quellzeichensatz ein Tabulatorzeichen enthält, und Zeichenfolgen- und Zeichenliterale können alle Zeichen im Quellzeichensatz enthalten, mit Ausnahme von umgekehrtem Schrägstrich, Anführungszeichen oder Apostroph (je nach Bedarf) und Zeilenumbruch.

Es ist also tragbar. Aber es ist keine gute Idee, da ein Leser nicht zwischen verschiedenen Arten von Leerzeichen unterscheiden kann. Es ist auch ziemlich üblich, dass Texteditoren, E-Mail-Programme und dergleichen Registerkarten neu formatieren, so dass im Verlauf solcher Operationen Fehler in das Programm eingeführt werden können.

  • Stimmen Sie zu: „Es ist keine gute Idee“. Angenommen, der Quellcode könnte einen Rohwagenrücklauf einbetten '\r' (oder vertikaler Tabulator, Seitenvorschub) in einer Zeichenfolge, Now diese wäre interessant, in einem Code-Listing zu entziffern.

    – chux – Wiedereinsetzung von Monica

    6. März 2015 um 20:02 Uhr

  • @chux Sie können, zumindest VT und FF. Und ich stimme zu, dass sie es nicht tun sollten.

    – Christoph Creutzig

    6. März 2015 um 20:29 Uhr

Wenn Sie einen Tabulator in eine Eingabe eingeben, enthält Ihre Zeichenfolge ein wörtliches Tabulatorzeichen und bleibt ein Tabulatorzeichen – es wird nicht auf magische Weise übersetzt \t im Inneren.

Dasselbe gilt für das Schreiben von Code – Sie können wörtliche Tabulatorzeichen in Ihre Zeichenfolgen einbetten. Bedenken Sie jedoch Folgendes:

     T     T     T        <--tab stops
012345012345012345012345
foo1 = 'a\tb';
foo2 = 'a  b'; // pressed tab in the editor
foo3 = 'a  b'; // hit space twice in the editor

Es sei denn, Sie setzen den Cursor auf das Leerzeichen dazwischen a und b und überprüft, wie viele Zeichen darin enthalten sind, gibt es im Wesentlichen KEINE Möglichkeit festzustellen, ob dort ein Tabulator oder tatsächliche Leerzeichen vorhanden sind. Aber mit dem \t Version wird es sofort als Registerkarte angezeigt.

  • “es wird intern nicht auf magische Weise in \t übersetzt” – wissen Sie zufällig wann \t wird dann in eine Registerkarte übersetzt? (Und ob es tatsächlich eine nützliche Tatsache ist, dies zu wissen.)

    – Jongware

    6. März 2015 um 14:41 Uhr

  • zur Kompilierzeit. das \t existiert nur in der Textversion Ihres Codes. Sobald der Compiler fertig ist, enthält die Binär-/Objektdatei ASCII-Zeichen 9 (ein Byte), nicht \t (zwei Byte).

    – Markus B

    6. März 2015 um 14:42 Uhr

  • Das sind die beiden Endpunkte des Prozesses 😊 Ich denke, es ist sicher anzunehmen, dass es Teil des Standards ist Schnur wird bearbeitet. Was mich daran erinnert: Dasselbe muss für die einzelne Zeichenkonstante gelten '\t'. (Ah warte: das steht auch in der Spezifikation, wie Mike zeigt.)

    – Jongware

    6. März 2015 um 14:46 Uhr

  • Mein Editor zeigt Leerzeichen, Leerzeichen und Tabulatoren sind dort ziemlich unterschiedlich

    – Ratschenfreak

    6. März 2015 um 15:35 Uhr

  • @Jongware: Dies geschieht in Übersetzungsphase 5, dh nach der Vorverarbeitung und vor der Verkettung benachbarter Zeichenfolgenliterale. (“5. Jedes Element des Quellzeichensatzes und jede Escape-Sequenz in Zeichenkonstanten und Zeichenfolgenliteralen wird in das entsprechende Element des Ausführungszeichensatzes konvertiert; wenn es kein entsprechendes Element gibt, wird es in ein von der Implementierung definiertes Element konvertiert, bei dem es sich nicht um null handelt (breiter) Charakter.”) Ob das nützlich ist zu wissen, ist eine Funktion des Wissenden 🙂

    – Rici

    6. März 2015 um 18:58 Uhr


Wenn Sie die TAB-Taste drücken, erhalten Sie den Codepunkt, dem Ihr System diese Taste zuordnet. Dieser Codepunkt kann eine Registerkarte auf dem System sein, auf dem das Programm ausgeführt wird, oder auch nicht. Wenn Sie \t in ein Literal einfügen, ersetzt der Compiler es durch den entsprechenden Codepunkt für das Zielsystem. Wenn Sie also sicher sein wollen, dass Sie einen Tab auf dem System erhalten, auf dem das Programm läuft, verwenden Sie \t. Das ist seine Aufgabe.

1411140cookie-checkIst es obligatorisch, Tabulatorzeichen in C und C++ zu maskieren?

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

Privacy policy