2012-11-18 20 views
14

Von Wikipedia:ist die wörtliche u8 Zeichenfolge notwendig in C++ 11

Zur Unterstützung in C++ Compiler für Unicode der Verbesserung, die Definition des Typs char geändert wurde zumindest der Größe zu sein notwendig, um eine Acht-Bit-Codierung von UTF-8 zu speichern.

Ich frage mich, was genau das bedeutet für tragbare Anwendungen zu schreiben. Gibt es einen Unterschied zwischen dem Schreiben dieses

const char[] str = "Test String"; 

oder dies?

const char[] str = u8"Test String"; 

Gibt es einen Grund, letzteres nicht für jedes Zeichenfolgenliteral in Ihrem Code zu verwenden?

Was passiert, wenn es nicht-ASCII-Zeichen in dem Teststring?

+1

http://stackoverflow.com/questions/9739070/char-encoding könnte – Yakk

+7

Einer der Saiten ist UTF-8, der andere könnte alles sein, wie EBCDIC nützlich sein. –

+0

Vielleicht von Interesse - einige codierungsbezogene Fragen von mir: [# 1] (http://stackoverflow.com/questions/6300804/wchars-cododes-standards-and-portability), [# 2] (http: // /stackoverflow.com/questions/6796157/unicode-encoding-for-string-literals-in-c0x), [# 3] (http://stackoverflow.com/questions/7562609/what-does-cuchar-provide-and -wo-ist-es-dokumentiert) –

Antwort

18

Die Codierung "Test String" ist die Implementierung definiert Systemcodierung (die schmale, möglicherweise Multibyte eins).

Die Codierung u8"Test String" ist immer UTF-8.

Die Beispiele sind nicht sehr aufschluss. Wenn Sie einige Unicode-Literale (z. B. \U0010FFFF) in die Zeichenfolge einschließen, erhalten Sie diese immer (codiert als UTF-8), aber ob sie in der systemcodierten Zeichenfolge ausgedrückt werden könnten und wenn ja, wie groß wäre ihr Wert , ist implementierungsdefiniert.

Wenn es hilft, stellen Sie sich auf einer EBCDIC-Maschine den Quellcode sind Authoring. Dann ist das Literal "Test String" immer EBCDIC-codiert in der Quelldatei selbst, aber das u8 -initialisierte Array enthält UTF-8-codierte Werte, während das erste Array EBCDIC-codierte Werte enthält.

4

Der Compiler wählt eine native Codierung natürliche an die Plattform. Bei typischen POSIX-Systemen wird es wahrscheinlich ASCII und etwas anderes wählen, abhängig von der Einstellung der Umgebung für Zeichenwerte außerhalb des ASCII-Bereichs. Auf Mainframes wird es wahrscheinlich EBCDIC wählen. Das Vergleichen von Strings, die beispielsweise von Dateien oder der Befehlszeile empfangen werden, funktioniert wahrscheinlich am besten mit dem nativen Zeichensatz. Bei der Verarbeitung von Dateien, die explizit mit UTF-8 codiert wurden, sollten Sie jedoch wahrscheinlich u8"..." Strings verwenden.

Das hieß, mit den aktuellen Änderungen in Zeichenkodierungen Zusammenhang eine grundlegende Annahme einer Kettenverarbeitung in C und C++ gebrochen wurde: jedes internes Zeichenobjekt (char, wchar_t, etc.) verwendet, um ein Zeichen darzustellen. Dies ist eindeutig nicht mehr wahr für eine UTF-8-Zeichenfolge, bei der jedes Zeichenobjekt nur ein Byte eines Zeichens darstellt. Daher funktionieren die Funktionen für die Zeichenfolgenmanipulation, Zeichenklassifizierung usw. nicht unbedingt mit diesen Zeichenfolgen. Wir haben keine gute Bibliothek zur Verfügung, um solche Strings für die Aufnahme in den Standard zu bearbeiten.

+0

Char ist seit langem dafür bekannt, möglicherweise Multi-Byte zu sein (dh, Programmierer, die ein Zeichen pro Zeichen annahmen, taten es falsch). Auf der anderen Seite benötigt wchar_t eine feste Breite. Leider bricht Unicode die Annahmen darüber grundlegend, was "feste Breite" bedeutet. – bames53

+0

Ich stimme nicht unbedingt mit der Tatsache überein, dass Zeichenketten seit einiger Zeit verwendet werden, um Multi-Byte-Codierung zu halten, aber der Standard hat diese Tatsache nicht anerkannt und interne Zeichen als eine Einheit behandelt. Alle Standard-Verarbeitungszeichenfolgen verhalten sich immer noch so, als wären Zeichen nur eine Einheit! Zum Beispiel ist es nicht wirklich sinnvoll, wenn man "sstr (b, n)" hat, wenn der Anfang und/oder das Ende des Teilstrings in der Mitte eines Unicode-Zeichens stehen kann. Sogar "wchar_t" -Strings haben Zeichen mit fester Breite, da es beispielsweise Zeichen kombiniert. –

+0

@ DietmarKühl: "aber der Standard hat diese Tatsache nicht anerkannt", ich denke du meinst * in den Bibliotheksfunktionen *. Der C++ - Standard selbst hat immer die Existenz von Multibyte-Zeichenketten erkannt. zum Beispiel, es empfiehlt/benötigt (ich erinnere mich nicht genau welche), dass "Haupt" Argumente sind MBCSes, wo die Windows-Konvention fehlschlägt - oder, wo der Standard bestehende Praxis nicht ordnungsgemäß standardisieren ... ;-) –

13

Sie zitieren Wikipedia:

Für die Zwecke ++ Compiler in C Unterstützung für Unicode-Verbesserung, die Definition des Typs char wurde geändert notwendig, zumindest die Größe zu sein, eine Acht-Bit-Codierung von speichern UTF-8.

Nun, die “ Zum Zweck ” ist Bullshit. char war immer garantiert, mindestens 8 Bit zu sein, das heißt, CHAR_BIT war immer erforderlich, ≥ 8, aufgrund der Bereich char in der C-Norm erforderlich. Was ist (Zitat C++ 11 §17.5.1.5/1) “ ” in den C++ Standard aufgenommen.

Wenn ich über die Zweck dieser Änderung der Formulierung raten sollte, wäre es nur Dinge für diejenigen Leser zu klären, die nicht von der Abhängigkeit von der C-Norm wissen.

die Wirkung des u8 wörtlichen Präfix In Bezug auf das

  • die Codierung der Zeichenfolge in der ausführbaren Datei betrifft, sondern

  • es leider nicht Einfluss auf die Art.

So wird in beiden Fällen "tørrfisk" und u8"tørrfisk" Sie erhalten eine char const[n]. Aber in dem früheren Literal ist die Codierung, was auch immer für den Compiler ausgewählt wird, z. Mit Latin 1 (oder Windows ANSI Western) wären das 8 Bytes für die Zeichen und ein Nullbyte für die Arraygröße 9. Während im letzteren Literal die Codierung garantiert UTF-8 ist, wird die “ ø ” mit codiert 2 oder 3 Bytes (ich don ’ t erinnere mich genau), für eine etwas größere Array-Größe.

0

Wenn der Ausführungszeichensatz des Compilers in UTF-8 gesetzt ist, macht es keinen Unterschied, wenn u8 verwendet wird oder nicht, da der Compiler die Zeichen in UTF-8 in beiden Fällen umwandelt.

Wenn jedoch der Compiler-Ausführungszeichensatz die Nicht-UTF8-Codepage des Systems ist (Standardeinstellung für z. B. Visual C++), werden möglicherweise nicht ASCII-Zeichen nicht richtig behandelt, wenn u8 weggelassen wird. Zum Beispiel stürzt die Umwandlung in breite Strings z.B. in VS15:

std::string narrowJapanese("スタークラフト"); 
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convertWindows; 
std::wstring wide = convertWindows.from_bytes(narrowJapanese); // Unhandled C++ exception in xlocbuf.