Ist C++ 20 'char8_t' dasselbe wie unser altes 'char'?




c++14 c++20 (2)

In der CPP-Referenzdokumentation

Ich bemerkte für char

Die Zeichentypen sind groß genug, um jede UTF-8-Acht-Bit-Codeeinheit darzustellen (seit C ++ 14).

und für char8_t

Typ für UTF-8-Zeichendarstellung, der groß genug sein muss, um eine beliebige UTF-8-Codeeinheit (8 Bit) darzustellen

Bedeutet das, dass beide vom selben Typ sind? Oder hat char8_t eine andere Funktion?


Haftungsausschluss: Ich bin der Autor der Vorschläge char8_t P0482 und P1423 .

In C ++ 20 unterscheidet sich char8_t von allen anderen Typen. In dem verwandten Vorschlag für C, N2231 (der eine Aktualisierung und einen erneuten Vorschlag für WG14 erfordert) wäre char8_t eine Typdefinition für unsigned char Zeichen, ähnlich den vorhandenen Typdefinitionen für char16_t und char32_t .

In C ++ 20 hat char8_t eine zugrunde liegende Darstellung, die mit dem unsigned char char8_t übereinstimmt. Es hat daher die gleiche Größe (mindestens 8-Bit, kann aber größer sein), Ausrichtung und ganzzahlige Konvertierungsrang wie unsigned char , verfügt jedoch über andere Aliasing-Regeln.

Insbesondere wurde char8_t auf [basic.lval]p11 nicht zur char8_t hinzugefügt. [basic.life]p6.4 , [basic.types]p2 oder [basic.types]p4 . Dies bedeutet, dass es im Gegensatz zu unsigned char weder für die zugrunde liegende Speicherung von Objekten eines anderen Typs noch für die Untersuchung der zugrunde liegenden Darstellung von Objekten eines anderen Typs verwendet werden kann. Mit anderen Worten, es kann nicht verwendet werden, um andere Typen zu aliasen. Dies hat zur Folge, dass auf Objekte vom Typ char8_t über Zeiger auf char oder unsigned char char8_t kann, während Zeiger auf char8_t nicht für den Zugriff auf char8_t oder unsigned char Daten verwendet werden können. Mit anderen Worten:

reinterpret_cast<const char   *>(u8"text"); // Ok.
reinterpret_cast<const char8_t*>("text");   // Undefined behavior.

Die Motivation für einen bestimmten Typ mit diesen Eigenschaften ist:

  1. Festlegen eines eindeutigen Typs für UTF-8-Zeichendaten im Vergleich zu Zeichendaten mit einer Codierung, die entweder vom Gebietsschema abhängig ist oder eine separate Angabe erfordert.

  2. Aktivieren der Überladung für normale String-Literale gegenüber UTF-8-String-Literalen (da diese möglicherweise unterschiedliche Codierungen haben).

  3. Um einen vorzeichenlosen Typ für UTF-8-Daten sicherzustellen (ob char signiert oder nicht signiert ist, ist in der Implementierung definiert).

  4. Um eine bessere Leistung über einen Non-Aliasing-Typ zu ermöglichen; Optimierer können Typen besser optimieren, die keinen Alias ​​für andere Typen haben.


char8_t ist nicht dasselbe wie char . Es verhält sich genauso wie das [basic.fundamental]/9 unsigned char gemäß [basic.fundamental]/9

Der Typ char8_t bezeichnet einen bestimmten Typ, dessen zugrunde liegender Typ ein unsigned char char8_t ist . Die Typen char16_t und char32_t bezeichnen unterschiedliche Typen, deren zugrunde liegende Typen in <cstdint>. uint_least16_t bzw. uint_least32_t sind <cstdint>.

Hervorhebung von mir

Beachten Sie, dass der Standard einen eigenen Typ nennt, der dem Code ähnelt

std::cout << std::is_same_v<unsigned char, char8_t>;

gibt 0 (false) aus, obwohl char8_t als unsigned char char8_t implementiert ist. Dies liegt daran, dass es sich nicht um einen Alias ​​handelt, sondern um einen bestimmten Typ.

Zu beachten ist auch, dass char entweder als signed char oder unsigned char implementiert werden kann. Das bedeutet, dass char denselben Bereich und dieselbe Darstellung wie char8_t kann, es sich jedoch weiterhin um separate Typen handelt. char , signed char , unsigned char und char8_t haben dieselbe Größe, sind jedoch alle unterschiedliche Typen.





c++20