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.
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
, \u
und \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 char
s 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_t
oder 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.
GCC kodiert
u"\U0010FFFF"
in ein Ersatzpaar.– kennytm
22. Juli 2011 um 21:30 Uhr