string c++17 - Wann haben C++-Compiler angefangen, mehr als zwei Hex-Ziffern in Zeichenfolgen für Zeichenfolgenliterale zu berücksichtigen?




/std:c++17 c++20 (6)

Ich habe eine (generierte) Literal-Zeichenfolge in C ++, die Zeichen enthalten kann, die mit der \x Notation mit Escapezeichen versehen werden müssen. Zum Beispiel:

char foo[] = "\xABEcho";

G ++ (Version 4.1.2, wenn es darauf ankommt) löst jedoch einen Fehler aus:

test.cpp:1: error: hex escape sequence out of range

Der Compiler scheint die Ec Zeichen als Teil der vorangehenden Hex-Nummer zu betrachten (weil sie wie Hex-Ziffern aussehen). Da eine vierstellige Hexadezimalzahl nicht in ein char passt, wird ein Fehler ausgegeben. Für ein breites String-Literal L"\xABEcho" das erste Zeichen natürlich U + ABEC, gefolgt von L"ho" .

Es scheint, dass sich dies in den letzten Jahrzehnten irgendwann geändert hat und ich habe es nie bemerkt. Ich bin fast sicher, dass alte C-Compiler nach \x nur zwei Hex-Ziffern berücksichtigen und nicht weiter suchen würden.

Ich kann mir eine Problemumgehung dafür vorstellen:

char foo[] = "\xAB""Echo";

aber das ist ein bisschen hässlich. Ich habe also drei Fragen:

  • Wann hat sich das geändert?

  • Warum akzeptiert der Compiler nicht nur> 2-stellige Hex-Escape-Zeichen für Wide-String-Literale?

  • Gibt es einen Workaround, der weniger umständlich ist als der oben genannte?


Answers

Ich habe Antworten auf meine Fragen gefunden:

  • C ++ war schon immer so (überprüfte Stroustrup 3rd Edition, hatte vorher keine). K & R 1st Edition erwähnte \x überhaupt nicht (die einzigen verfügbaren Escape-Zeichen waren zu diesem Zeitpunkt oktal). K & R 2nd Edition besagt:

    '\xhh'

    Dabei ist hh eine oder mehrere Hexadezimalziffern (0 ... 9, a ... f, A ... F).

    Es scheint also, dass dieses Verhalten seit ANSI C existiert.

  • Während der Compiler möglicherweise nur> 2 Zeichen für Wide-String-Literale akzeptiert, würde dies die Grammatik unnötig komplizieren.

  • Es gibt tatsächlich eine weniger umständliche Lösung:

    char foo[] = "\u00ABEcho";

    Das \u Escape akzeptiert immer vier Hex-Ziffern.

Update : Die Verwendung von \u ist nicht in allen Situationen anwendbar, da die meisten ASCII-Zeichen (aus irgendeinem Grund) nicht mit \u angegeben werden dürfen. Hier ist ein Ausschnitt aus GCC:

/* The standard permits $, @ and ` to be specified as UCNs.  We use
     hex escapes so that this also works with EBCDIC hosts.  */
  else if ((result < 0xa0
            && (result != 0x24 && result != 0x40 && result != 0x60))
           || (result & 0x80000000)
           || (result >= 0xD800 && result <= 0xDFFF))
    {
      cpp_error (pfile, CPP_DL_ERROR,
                 "%.*s is not a valid universal character",
                 (int) (str - base), base);
      result = 1;
    }

GCC folgt nur dem Standard . #877 : "Jede [...] hexadezimale Escape-Sequenz ist die längste Zeichenfolge, die die Escape-Sequenz bilden kann."


Ich bin mir ziemlich sicher, dass C ++ schon immer so war. In jedem Fall kann CHAR_BIT größer als 8 sein. In diesem Fall '\xABE' oder '\xABEc' gültig sein.


Ich habe das Problem gelöst, indem ich das folgende Zeichen auch mit \ xnn angegeben habe. Leider müssen Sie dies so lange verwenden, wie Zeichen im Bereich [a..f] vorhanden sind. Ex. "\ xnneceg" wird ersetzt durch "\ xnn \ x65 \ x63 \ x65g"


Dies sind Breitzeichen-Literale.

char foo[] = "\x00ABEcho";

Könnte besser sein.

Hier sind einige Informationen, nicht gcc, aber immer noch zutreffend.

http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.iseries.pgmgd.doc/cpprog624.htm

Dieser Link enthält die wichtige Zeile:

Die Angabe von \xnn in einem \xnn wchar_t entspricht der Angabe von \x00nn

Dies kann auch hilfreich sein.

http://www.gnu.org/s/hello/manual/libc/Extended-Char-Intro.html#Extended-Char-Intro


Klingt gut zu überprüfen.

  • Visual Studio 2010 (unter Windows 7) können Sie 1011 Ebenen haben, bevor Sie diesen Fehler erhalten:

    fataler Fehler C1026: Parser-Stack-Überlauf, Programm zu komplex

  • gcc (Ubuntu), 100k + * ohne Absturz! Ich denke, die Hardware ist hier das Limit.

(getestet mit nur einer Variablendeklaration)





c++ string escaping literals