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

82

Nach einer verwandten 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 String-Literalen haben. Die Zeichentypen:

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/ \UZeichenreferenzen mit allen Zeichenfolgentypen frei kombinierbar? Haben alle Zeichenfolgentypen eine feste Breite, dh die Arrays enthalten genau so viele Elemente, wie im Literal erscheinen, oder werden \x/ \u/ \UVerweise auf eine variable Anzahl von Bytes erweitert? Haben u""und u8""Strings eine Codierungssemantik, z. B. kann ich 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? Kann ich in (1) einsame Ersatzzeichen mit schreiben \u? Ist schließlich eine der codierenden Zeichenfolgenfunktionen bekannt (dh sie sind zeichenbewusst und können ungültige Bytesequenzen erkennen)?

Dies ist eine offene Frage, aber ich möchte ein möglichst vollständiges Bild der neuen UTF-Codierungs- und Typfunktionen des neuen C ++ 11 erhalten.

Kerrek SB
quelle
4
GCC codiert u"\U0010FFFF"in ein Ersatzpaar.
Kennytm

Antworten:

55

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

Nein \xkann alles verwendet werden, aber \uund \Ukann nur in Zeichenketten verwendet werden , die speziell UTF-codiert sind. Jedoch für jede UTF-codierte Zeichenfolge \uund \Ukann nach Belieben verwendet werden.

Sind alle Zeichenfolgentypen mit fester Breite, dh enthalten die Arrays genau so viele Elemente, wie im Literal erscheinen, oder werden \ x / \ u / \ U-Referenzen auf eine variable Anzahl von Bytes erweitert?

Nicht so wie du meinst. \x,, \uund \Uwerden basierend auf der Zeichenfolgencodierung konvertiert. Die Anzahl dieser "Codeeinheiten" (unter Verwendung von Unicode-Begriffen. A char16_tist eine UTF-16-Codeeinheit) hängt von der Codierung der enthaltenen Zeichenfolge ab. Das Literal u8"\u1024"würde eine Zeichenfolge erstellen, die 2 chars plus einen Nullterminator enthält. Das Literal u"\u1024"würde eine Zeichenfolge erstellen, die 1 char16_tplus einen Nullterminator enthält.

Die Anzahl der verwendeten Codeeinheiten basiert auf der Unicode-Codierung.

Haben u "" - und u8 "" - Zeichenfolgen eine Codierungssemantik, z. B. kann ich char16_t x [] = u "\ U0010FFFF" sagen, 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 Ersatzzeichen mit \ u schreiben?

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

Sind schließlich eine der codierenden Zeichenfolgenfunktionen bekannt (dh sie sind zeichenbewusst und können ungültige Byte-Sequenzen erkennen)?

Absolut nicht. Gestatten Sie mir, das umzuformulieren.

std::basic_stringbehandelt keine Unicode-Codierungen. Sie können sicherlich UTF-codierte Zeichenfolgen speichern . Aber sie können denken nur von ihnen als Folge von char, char16_toder char32_t; Sie können sie nicht als eine Folge von Unicode-Codepunkten betrachten, die mit einem bestimmten Mechanismus codiert sind. basic_string::length()gibt die Anzahl der Codeeinheiten zurück, nicht die Codepunkte. Und offensichtlich sind die Zeichenfolgenfunktionen der C-Standardbibliothek völlig nutzlos

Es ist jedoch zu beachten, dass "Länge" für eine Unicode-Zeichenfolge nicht die Anzahl der Codepunkte bedeutet. Einige Codepunkte kombinieren "Zeichen" (ein unglücklicher Name), die mit dem vorherigen Codepunkt kombiniert werden. 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äß an den verschiedenen Stellen zu platzieren. Das ist leichter gesagt als getan, und ich habe keinen Code, der Ihnen zeigt, wie.

Nicol Bolas
quelle
7
@Philipp: Nein, das sind sie nicht. Unicode reserviert sie speziell für UTF-16-Ersatzzeichen. Wie bereits erwähnt, besagt die Spezifikation von C ++ 0x, dass die Kompilierung fehlschlägt, wenn Sie versuchen, einen Codepunkt in diesem Bereich zu bestimmen.
Nicol Bolas
12
Ihr Link beweist, dass es sich um Codepunkte handelt. Wenn Sie Wikipedia nicht vertrauen, lesen Sie die Definitionen 9 und 10 in Kapitel 3 des Standards. Ersatzcodepunkte in Zeichenfolgenliteralen sind in C ++ 0x jedoch gemäß Regel § 2.4 / 2 verboten.
Philipp
1
Nach dem Lesen bestätige ich auch, dass Ersatzcodepunkte in Zeichenfolgenliteralen akzeptiert werden.
George Kourtis
In C11 \xkann nichts verwendet werden, z. B. funktioniert U + 1F984 nicht mit dem Präfix \ x \uund \Ukann nicht mit ASCII-Steuerzeichen verwendet werden, zumindest in Clang.
MarcusJ