C99 oder früher
Der C-Standard (C99) sieht breite Zeichen und Multi-Byte-Zeichen vor, aber da es keine Garantie dafür gibt, was diese breiten Zeichen enthalten können, ist ihr Wert etwas begrenzt. Für eine bestimmte Implementierung bieten sie nützliche Unterstützung, aber wenn Ihr Code in der Lage sein muss, zwischen verschiedenen Implementierungen zu wechseln, gibt es keine ausreichende Garantie, dass sie nützlich sind.
Folglich ist der von Hans van Eck vorgeschlagene Ansatz (einen Wrapper um die ICU - International Components for Unicode - Bibliothek herum zu schreiben), IMO, vernünftig.
Die UTF-8-Kodierung hat viele Vorteile. Einer davon ist, dass die Daten, wenn man sie nicht manipuliert (z. B. durch Abschneiden), von Funktionen kopiert werden können, die die Feinheiten der UTF-8-Kodierung nicht kennen. Dies ist kategorisch nicht der Fall bei wchar_t
.
Unicode in voller Länge ist ein 21-Bit-Format. Das heißt, Unicode reserviert Codepunkte von U+0000 bis U+10FFFF.
Eines der nützlichen Dinge an den Formaten UTF-8, UTF-16 und UTF-32 (wobei UTF für Unicode Transformation Format steht - siehe Unicode ) ist, dass man zwischen den drei Darstellungen ohne Informationsverlust konvertieren kann. Jedes Format kann alles darstellen, was auch die anderen darstellen können. Sowohl UTF-8 als auch UTF-16 sind Multibyte-Formate.
UTF-8 ist bekanntlich ein Multi-Byte-Format mit einer sorgfältigen Struktur, die es ermöglicht, den Anfang von Zeichen in einer Zeichenkette zuverlässig zu finden, und zwar an jeder Stelle der Zeichenkette. Bei Einzelbyte-Zeichen ist das High-Bit auf Null gesetzt. Bei Multi-Byte-Zeichen beginnt das erste Zeichen mit einem der Bitmuster 110, 1110 oder 11110 (für 2-Byte-, 3-Byte- oder 4-Byte-Zeichen), wobei die nachfolgenden Bytes immer mit 10 beginnen. Die Fortsetzungszeichen liegen immer im Bereich 0x80 0xBF. Es gibt Regeln, dass UTF-8-Zeichen im kleinstmöglichen Format dargestellt werden müssen. Eine Folge dieser Regeln ist, dass die Bytes 0xC0 und 0xC1 (auch 0xF5..0xFF) in gültigen UTF-8-Daten nicht vorkommen können.
U+0000 .. U+007F 1 byte 0xxx xxxx
U+0080 .. U+07FF 2 bytes 110x xxxx 10xx xxxx
U+0800 .. U+FFFF 3 bytes 1110 xxxx 10xx xxxx 10xx xxxx
U+10000 .. U+10FFFF 4 bytes 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
Ursprünglich hatte man gehofft, dass Unicode ein 16-Bit-Codesatz sein würde und alles in einen 16-Bit-Codebereich passen würde. Leider ist die reale Welt komplexer, und der Code musste auf die aktuelle 21-Bit-Kodierung erweitert werden.
UTF-16 ist also ein Einheitscode (16-Bit-Wort) für die "Basic Multilingual Plane", d. h. die Zeichen mit den Unicode-Codepunkten U+0000 U+FFFF, verwendet aber zwei Einheiten (32-Bit) für Zeichen außerhalb dieses Bereichs. Daher muss Code, der mit der UTF-16-Kodierung arbeitet, in der Lage sein, Kodierungen mit variabler Breite zu handhaben, genau wie UTF-8. Die Codes für die Zeichen mit zwei Einheiten werden Surrogate genannt.
Surrogate sind Codepunkte aus zwei speziellen Bereichen von Unicode-Werten, die für die Verwendung als führende und nachfolgende Werte von gepaarten Codeeinheiten in UTF-16 reserviert sind. Führende, auch hohe Surrogate genannt, reichen von U+D800 bis U+DBFF, und nachgestellte oder niedrige Surrogate reichen von U+DC00 bis U+DFFF. Sie werden Surrogate genannt, da sie nicht direkt Zeichen darstellen, sondern nur als Paar.
UTF-32 kann natürlich jeden Unicode-Codepunkt in einer einzigen Speichereinheit kodieren. Es ist effizient für Berechnungen, aber nicht für die Speicherung.
Viele weitere Informationen finden Sie auf der INTENSIVSTATION und Unicode-Websites.
C11 und <uchar.h>
Mit der C11-Norm wurden die Regeln geändert, aber selbst jetzt (Mitte 2017) haben noch nicht alle Implementierungen mit den Änderungen Schritt gehalten. Der C11-Standard fasst die Änderungen für die Unicode-Unterstützung wie folgt zusammen:
- Unicode-Zeichen und -Strings (
<uchar.h>
) (ursprünglich spezifiziert in ISO/IEC TR 19769:2004)
Im Folgenden wird nur ein minimaler Überblick über die Funktionalität gegeben. Die Spezifikation umfasst:
6.4.3 Universelle Zeichennamen
Syntax
Universal-Zeichen-Name:
\u
hex-quad
\U
hex-quad hex-quad
hex-quad:
hexadezimal-stellig hexadezimal-stellig hexadezimal-stellig hexadezimal-stellig
7.28 Unicode-Hilfsmittel <uchar.h>
Die Überschrift <uchar.h>
deklariert Typen und Funktionen für die Bearbeitung von Unicode-Zeichen.
Die deklarierten Typen sind mbstate_t
(beschrieben in 7.29.1) und size_t
(beschrieben in 7.19);
char16_t
ist ein vorzeichenloser Integer-Typ, der für 16-Bit-Zeichen verwendet wird und der gleiche Typ ist wie uint_least16_t
(beschrieben in 7.20.1.2); und
char32_t
ist ein vorzeichenloser Integer-Typ, der für 32-Bit-Zeichen verwendet wird und der gleiche Typ ist wie uint_least32_t
(auch beschrieben in 7.20.1.2).
(Ich übersetze die Querverweise: <stddef.h>
definiert size_t
, <wchar.h>
definiert mbstate_t
, und <stdint.h>
definiert uint_least16_t
y uint_least32_t
.) Die <uchar.h>
Kopfzeile definiert auch einen minimalen Satz von (neu startbaren) Konvertierungsfunktionen:
mbrtoc16()
c16rtomb()
mbrtoc32()
c32rtomb()
Es gibt Regeln dafür, welche Unicode-Zeichen in Bezeichnern verwendet werden können, die die \unnnn
ou \U00nnnnnn
Notizen. Möglicherweise müssen Sie die Unterstützung für solche Zeichen in Bezeichnern aktiv aktivieren. Der GCC verlangt zum Beispiel -fextended-identifiers
um diese in Bezeichnern zuzulassen.
Beachten Sie, dass macOS Sierra (10.12.5), um nur eine Plattform zu nennen, die folgenden Funktionen nicht unterstützt <uchar.h>
.