Wie fügt man Hex-Escapes richtig in ein String-Literal ein?

Lesezeit: 4 Minuten

Benutzeravatar von tilz0R
bis0R

Wenn Sie eine Zeichenfolge in C haben, können Sie darin direkten Hex-Code hinzufügen.

char str[] = "abcde"; // 'a', 'b', 'c', 'd', 'e', 0x00
char str2[] = "abc\x12\x34"; // 'a', 'b', 'c', 0x12, 0x34, 0x00

Beide Beispiele haben 6 Bytes im Speicher. Nun besteht das Problem, wenn Sie Mehrwert schaffen wollen [a-fA-F0-9] nach Hex-Eingabe.

//I want: 'a', 'b', 'c', 0x12, 'e', 0x00
//Error, hex is too big because last e is treated as part of hex thus becoming 0x12e
char problem[] = "abc\x12e";

Mögliche Lösung ist das Ersetzen nach der Definition.

//This will work, bad idea
char solution[6] = "abcde";
solution[3] = 0x12;

Das kann funktionieren, aber es wird fehlschlagen, wenn Sie es so formulieren const.

//This will not work
const char solution[6] = "abcde";
solution[3] = 0x12; //Compilation error!

Wie man richtig einfügt e nach \x12 ohne Fehler auszulösen?


Warum frage ich? Wenn Sie bauen möchten UTF-8 string als Konstante, müssen Sie hexadezimale Zeichenwerte verwenden, wenn sie größer sind als die ASCII-Tabelle aufnehmen kann.

  • Duplizieren: stackoverflow.com/questions/35180528/…. Ich werde diesen schließen, da ich denke, dass die hier geposteten Antworten vollständiger sind, wobei der Standard eher in der Antwort als in Kommentaren zitiert wird.

    – Ludin

    10. August 2017 um 12:41 Uhr


Benutzeravatar von user694733
Benutzer694733

Verwenden Sie 3 Oktalziffern:

char problem[] = "abc\022e";

oder teilen Sie Ihre Zeichenfolge:

char problem[] = "abc\x12" "e";

Warum diese funktionieren:

  • Im Gegensatz zu Hex-Escapes definiert Standard 3 Ziffern als maximale Anzahl für Oktal-Escapes.

    6.4.4.4 Zeichenkonstanten

    octal-escape-sequence:
        \ octal-digit
        \ octal-digit octal-digit
        \ octal-digit octal-digit octal-digit
    

    hexadecimal-escape-sequence:
        \x hexadecimal-digit
        hexadecimal-escape-sequence hexadecimal-digit
    
  • Die String-Literal-Verkettung ist als eine spätere Übersetzungsphase definiert als die Literal-Escape-Zeichenkonvertierung.

    5.1.1.2 Übersetzungsphasen

    1. Jedes Element des Quellzeichensatzes und jede Escape-Sequenz in Zeichenkonstanten und Zeichenfolgenliteralen wird in das entsprechende Element des Ausführungszeichensatzes konvertiert. Wenn kein entsprechendes Mitglied vorhanden ist, wird es in ein von der Implementierung definiertes Mitglied konvertiert, bei dem es sich nicht um das Nullzeichen (Breitzeichen) handelt. 8)

    2. Benachbarte String-Literal-Tokens werden verkettet.

  • Eine dritte Alternative besteht darin, alles explizit zu tun: char solution[] = {'a', 'b', 'c', 0x12, 'e', '\0'};

    – Ludin

    10. August 2017 um 12:38 Uhr

  • Oder kompensieren Sie sogar die Escape-Zeichenfolge vollständig. "abc" "\x12" "e"; zur Klarheit.

    – chux – Wiedereinsetzung von Monica

    10. August 2017 um 12:38 Uhr

Benutzeravatar von paxdiablo
paxdiablo

Da Zeichenfolgenliterale schon früh im Kompilierungsprozess verkettet werden, aber nach die Umwandlung von Escape-Zeichen können Sie einfach verwenden:

char problem[] = "abc\x12" "e";

obwohl Sie möglicherweise eine vollständige Trennung für die Lesbarkeit bevorzugen:

char problem[] = "abc" "\x12" "e";

Für die Sprachanwälte unter uns ist dies abgedeckt C11 5.1.1.2 Translation phases (meine Betonung):

  1. Jedes Quellzeichensatzmitglied und Fluchtabfolge in Zeichenkonstanten und Zeichenfolgenliterale wird in das entsprechende Mitglied des Ausführungszeichensatzes konvertiert; Wenn kein entsprechendes Mitglied vorhanden ist, wird es in ein von der Implementierung definiertes Mitglied konvertiert, bei dem es sich nicht um das Nullzeichen (Breitzeichen) handelt.

  2. Benachbarte String-Literal-Tokens werden verkettet.

Warum frage ich? Wenn Sie eine UTF-8-Zeichenfolge als Konstante erstellen möchten, müssen Sie Hexadezimalwerte von Zeichen verwenden, die größer sind, als die ASCII-Tabelle aufnehmen kann.

Nun, nein. Du nicht müssen, zu … haben. Ab C11 können Sie Ihrer String-Konstante ein Präfix voranstellen u8die dem Compiler mitteilt, dass das Zeichenliteral in UTF-8 vorliegt.

char solution[] = u8"no need to use hex-codes á駵";

(Gleiches wird übrigens auch von C++11 unterstützt)

  • Die Leute fischen vielleicht nach den nicht druckbaren Zeichen 0 bis 31 der klassischen 7-Bit-ASCII-Tabelle.

    – Ludin

    10. August 2017 um 13:22 Uhr

  • @Lundin Sollten sie nicht lieber das Zeichen 0 weglassen …?

    – CiaPan

    10. August 2017 um 21:05 Uhr

  • @Damon C und C++ sind unterschiedliche Sprachen. Der C-Standard ist nicht derselbe (ich habe ihn nach Ihrem Text durchsucht und er wurde nicht gefunden). Sie können universelle Zeichenkonstanten verwenden, z u8"\u12345678"weil Backslash, u, 1 usw. sind im Quellzeichensatz; Das angegebene Unicode-Zeichen befindet sich jedoch möglicherweise nicht im Quellzeichensatz. Der Quellcode darf nur Zeichen aus dem Quellzeichensatz enthalten, was beispielsweise 7-Bit-ASCII sein könnte (dies hat nichts mit dem Ausführungszeichensatz zu tun).

    – MM

    15. August 2017 um 9:24 Uhr


  • @Damon, das ist eine C-Frage, und der C-Standard existiert, es gibt buchstäblich keinen Grund, C ++ einzubeziehen

    – MM

    15. August 2017 um 10:21 Uhr

  • Ich habe es bereits getan und in meinem vorherigen Kommentar erklärt. universal-character-name ist zulässig, da alle Zeichen, die so etwas umfassen, im grundlegenden Quellzeichensatz enthalten sind, Unicode-Zeichen jedoch möglicherweise nicht. Es ist implementierungsdefiniert, was in der ist erweiterter Quellzeichensatz und das könnte leer sein.

    – MM

    15. August 2017 um 12:32 Uhr


1413340cookie-checkWie fügt man Hex-Escapes richtig in ein String-Literal ein?

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

Privacy policy