Unicode-Codierung für Zeichenfolgenliterale in C++11

Lesezeit: 4 Minuten

Unicode Codierung fur Zeichenfolgenliterale in C11
Kerrek SB

Im Anschluss an eine verwandte Frage möchte ich nach den neuen Zeichen- und Zeichenfolgenliteraltypen in C++11 fragen. Es scheint, dass wir jetzt vier Arten von Zeichen und fünf Arten von Zeichenfolgenliteralen haben. Die Charaktertypen:

char     a="\x30";         // character, no semantics
wchar_t  b = L'\xFFEF';       // wide character, no semantics
char16_t c = u'\u00F6';       // 16-bit, assumed UTF16?
char32_t d = U'\U0010FFFF';   // 32-bit, assumed UCS-4

Und die String-Literale:

char     A[] =  "Hello\x0A";         // byte string, "narrow encoding"
wchar_t  B[] = L"Hell\xF6\x0A";      // wide string, impl-def'd encoding
char16_t C[] = u"Hell\u00F6";        // (1)
char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2)
auto     E[] = u8"\u00F6\U0010FFFF"; // (3)

Die Frage ist: Sind die \x/\u/\U Zeichenreferenzen frei kombinierbar mit allen Zeichenkettentypen? Sind alle String-Typen fester Breite, dh die Arrays enthalten genau so viele Elemente, wie im Literal vorkommen, oder bis \x/\u/\U Referenzen werden in eine variable Anzahl von Bytes erweitert? Machen u"" und u8"" Zeichenfolgen haben Codierungssemantik, kann ich zB sagen char16_t x[] = u"\U0010FFFF", und der Nicht-BMP-Codepunkt wird in eine UTF16-Sequenz mit zwei Einheiten codiert? Und ähnlich für u8? In (1) kann ich einzelne Surrogate mit schreiben \u? Sind schließlich einige der Zeichenfolgenfunktionen codierungsbewusst (dh sie sind zeichenbewusst und können ungültige Bytesequenzen erkennen)?

Dies ist eine etwas offene Frage, aber ich möchte mir ein möglichst vollständiges Bild von der neuen UTF-Codierung und den Typfunktionen des neuen C++ 11 machen.

  • GCC kodiert u"\U0010FFFF" in ein Ersatzpaar.

    – kennytm

    22. Juli 2011 um 21:30 Uhr


1646952010 969 Unicode Codierung fur Zeichenfolgenliterale in C11
Nicol Bola

Sind die Zeichenreferenzen \x/\u/\U mit allen Stringtypen frei kombinierbar?

Nein. \x kann in allem verwendet werden, aber \u und \U kann nur in Zeichenfolgen verwendet werden, die speziell UTF-codiert sind. Für jede UTF-codierte Zeichenfolge gilt jedoch: \u und \U kann verwendet werden, wie Sie es für richtig halten.

Sind alle String-Typen feste Breite, dh die Arrays enthalten genau so viele Elemente, wie im Literal vorkommen, oder werden auf \x/\u/\U-Referenzen in eine variable Anzahl von Bytes expandiert?

Nicht so, wie du meinst. \x, \uund \U werden basierend auf der Zeichenfolgencodierung konvertiert. Die Anzahl dieser “Codeeinheiten” (unter Verwendung von Unicode-Begriffen. A char16_t ist eine UTF-16-Codeeinheit) hängt von der Codierung der enthaltenden Zeichenfolge ab. Das wörtliche u8"\u1024" würde eine Zeichenfolge erstellen, die 2 enthält chars plus ein Null-Terminator. Das wörtliche u"\u1024" würde eine Zeichenfolge erstellen, die 1 enthält char16_t plus ein Null-Terminator.

Die Anzahl der verwendeten Codeeinheiten richtet sich nach der Unicode-Kodierung.

Haben die Zeichenfolgen u”” und u8″” eine Codierungssemantik, kann ich zB char16_t x sagen?[] = u”\U0010FFFF”, und der Nicht-BMP-Codepunkt wird in eine UTF16-Sequenz mit zwei Einheiten codiert?

u"" erstellt eine UTF-16-codierte Zeichenfolge. u8"" erstellt eine UTF-8-codierte Zeichenfolge. Sie werden gemäß der Unicode-Spezifikation codiert.

Kann ich in (1) einzelne Surrogate mit \u schreiben?

Absolut nicht. Die Spezifikation verbietet ausdrücklich die Verwendung der UTF-16-Ersatzpaare (0xD800-0xDFFF) als Codepoints für \u oder \U.

Sind schließlich einige der Zeichenfolgenfunktionen codierungsbewusst (dh sie sind zeichenbewusst und können ungültige Bytesequenzen erkennen)?

Absolut nicht. Nun, lassen Sie mich das umformulieren.

std::basic_string befasst sich nicht mit Unicode-Codierungen. Das können sie sicherlich Laden UTF-codierte Zeichenfolgen. Aber sie können sie sich nur als Folgen von vorstellen char, char16_toder char32_t; Sie können sie sich nicht als eine Folge von Unicode-Codepunkten vorstellen, die mit einem bestimmten Mechanismus codiert sind. basic_string::length() gibt die Anzahl der Codeeinheiten zurück, nicht die Codepunkte. Und offensichtlich sind die String-Funktionen der C-Standardbibliothek völlig nutzlos

Es sollte jedoch beachtet werden, dass “Länge” für einen Unicode-String nicht die Anzahl der Codepunkte bedeutet. Einige Codepunkte kombinieren “Zeichen” (ein unglücklicher Name), die sich mit dem vorherigen Codepunkt kombinieren. So können mehrere Codepunkte einem einzelnen visuellen Zeichen zugeordnet werden.

Iostreams können tatsächlich Unicode-codierte Werte lesen/schreiben. Dazu müssen Sie ein Gebietsschema verwenden, um die Codierung anzugeben und sie ordnungsgemäß in die verschiedenen Stellen einzufügen. Das ist leichter gesagt als getan, und ich habe keinen Code bei mir, der Ihnen zeigt, wie das geht.

  • @Philipp: Nein sind sie nicht. Unicode reserviert sie speziell für UTF-16-Ersatzzeichen. Und wie bereits erwähnt, sagt die Spezifikation von C++0x, dass die Kompilierung fehlschlagen wird, wenn Sie versuchen, einen Codepunkt in diesem Bereich festzulegen.

    – Nicol Bolas

    24. Juli 2011 um 19:41 Uhr


  • Ihr Link beweist, dass sie sind Codepunkte. Wenn Sie Wikipedia nicht vertrauen, lesen Sie die Definitionen 9 und 10 in Kapitel 3 des Standards. Ersatz-Codepunkte in String-Literalen sind jedoch in C++0x durch Regel § 2.4/2 verboten.

    – Philipp

    24. Juli 2011 um 21:36 Uhr

  • Nach dem Lesen bestätige ich auch, dass Surrogate-Codepunkte in String-Literalen akzeptiert werden.

    – Georg Kourtis

    27. Juli 2014 um 10:07 Uhr

  • In C11, \x kann mit nichts verwendet werden, zum Beispiel funktioniert U+1F984 nicht mit dem Präfix \x und \u und \U kann zumindest in Clang nicht mit ASCII-Steuerzeichen verwendet werden.

    – MarcusJ

    7. April 2018 um 11:47 Uhr


989180cookie-checkUnicode-Codierung für Zeichenfolgenliterale in C++11

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

Privacy policy