Was ist mit C ++ wchar_t und wstrings "falsch"? Was sind einige Alternativen zu breiten Zeichen?
Ich habe eine Menge Leute gesehen, die in der C++ community(besonders ##c++ auf freenode) ärgern sich über die Nutzung von wstrings
und wchar_t
und Ihre Anwendung in der windows-api. Was genau ist "falsch" mit wchar_t
und wstring
, und wenn ich will, um die Internationalisierung zu unterstützen, was sind einige alternativen zu wide-Zeichen?
Kommentar zu dem Problem
Haben die irgendwelche Referenzen?
Vielleicht ist diese awesome thread werden alle Ihre Fragen beantworten? stackoverflow.com/questions/402283/stdwstring-vs-stdstring
Auf Windows -, Sie haben nicht wirklich eine Wahl. Seine internen APIs wurden entwickelt für UCS-2, was vernünftig war zu der Zeit, da war es vor der variable-length-UTF-8 und UTF-16-Codierungen wurden standardisiert. Aber jetzt, mit Unterstützung UTF-16, hab Sie endete mit dem schlechtesten aus beiden Welten.
utf8everywhere.org hat eine gute Erläuterung der Gründe zu vermeiden wide-Zeichen.
@jamesdlin Sicherlich haben Sie die Wahl. nowide Bibliothek bietet eine bequeme Möglichkeit zum umwandeln von strings nur bei der übergabe an den APIs. API-Aufrufe mit Saiten sind in der Regel low-Frequenz, also der angemessene Weg ist, um konvertieren ad-hok und Dateien und interne Variablen in UTF-8 die ganze Zeit.
InformationsquelleAutor der Frage Ken Li | 2012-06-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
Was ist wchar_t?
wchar_t ist so definiert, dass alle lokalen char-Kodierung umgewandelt werden können, um einen wchar_t-Darstellung, wo jeder wchar_t stellt genau eine codepoint:
Diese nicht verlangen, dass wchar_t groß genug sein, um ein einzelnes Zeichen aus allen locales gleichzeitig. Das heißt, die verwendete Codierung für wchar_t kann sich zwischen locales. Was bedeutet, dass Sie nicht unbedingt Konvertierung einer Zeichenfolge in ein wchar_t verwenden eine locale und dann wieder zurück konvertieren in char mit einem anderen Gebietsschema.1
Da mit wchar_t als eine gemeinsame Repräsentation zwischen allen locales scheint der primäre nutzen für wchar_t in der Praxis könnten Sie sich Fragen, was es gut ist, wenn nicht,.
Den ursprünglichen Sinn und Zweck von wchar_t war, um text Bearbeiten einfacher durch das definieren Sie so, dass es erfordert eine eins-zu-eins-Zuordnung aus einer Zeichenkette code-Einheiten der text-Zeichen, so dass die Verwendung der gleichen einfache algorithmen verwendet werden, die mit ascii-strings, die für die Arbeit mit anderen Sprachen.
Leider ist der Wortlaut von wchar_t-Spezifikationen gehen von einer eins-zu-eins-Zuordnung zwischen den Zeichen und zeichenelemente, dies zu erreichen. Unicode-Pausen, Annahme2, also kann man nicht sicher mit wchar_t für einfache text-algorithmen.
Dies bedeutet, dass portable software nicht verwenden, wchar_t entweder als eine gemeinsame Repräsentation für text zwischen locales, oder aktivieren Sie die Verwendung von einfachen text-algorithmen.
Was wchar_t heute?
Nicht viel, für portablen code sowieso. Wenn
__STDC_ISO_10646__
definiert ist, dann werden die Werte von wchar_t direkt repräsentieren Unicode-codepoints mit den gleichen Werten in allen Gebietsschemas. Das macht es sicher inter-locale-Konvertierungen bereits erwähnt. Aber Sie können nicht Sie verlassen sich nur darauf zu entscheiden, dass Sie verwenden können, wchar_t diese Weise, weil, während die meisten unix-Plattformen definieren, die es Windows nicht, obwohl Windows verwendet die gleichen wchar_t locale in allen Gebietsschemas.Den Grund, dass Windows nicht definieren
__STDC_ISO_10646__
ist, weil Windows verwenden UTF-16 als Ihre wchar_t-encoding, und da UTF-16 verwendet ersatzzeichenpaare zu vertreten Codepoint größer als U+FFFF, was bedeutet, dass UTF-16 nicht erfüllen die Anforderungen für__STDC_ISO_10646__
.Für Plattform-spezifische code wchar_t kann nützlicher sein. Es ist im wesentlichen erforderlich, die auf Windows (z.B. einige Dateien können nicht einfach geöffnet werden ohne Verwendung von wchar_t Dateinamen), obwohl Windows ist die einzige Plattform, wo dies zutrifft, so weit ich weiß, (so können wir vielleicht denken, "wchar_t als "Windows_char_t').
Im Nachhinein wchar_t ist eindeutig nicht nützlich für die Vereinfachung der Verarbeitung von text, oder als Speicher für die locale-unabhängigen text. Portabler code sollte nicht versuchen, es zu benutzen für diese Zwecke. Nicht-portablen code finden es vielleicht nützlich, einfach, weil einige API erfordert.
Alternativen
Die alternative, die ich mag, ist die Verwendung von UTF-8-kodiert C-strings, sogar auf Plattformen, die nicht besonders freundlich in Richtung UTF-8.
Diese Weise kann man schreiben portablen code mit einem üblichen text-Darstellung auf allen Plattformen, Verwendung von standard-Datentypen für den beabsichtigten Zweck, bekommen die Sprache ist die Unterstützung für diese Typen (z.B. string-Literale, obwohl einige tricks nötig, damit es funktioniert für einige Compiler), einige standard-Bibliothek-Unterstützung, debugger-Unterstützung (mehr Stiche können erforderlich sein), etc. Mit der wide-Zeichen, ist es generell schwieriger oder unmöglich machen, um alle diese, und Sie erhalten möglicherweise unterschiedliche Stücke auf verschiedenen Plattformen.
Eins UTF-8 nicht erbringen, ist die Fähigkeit, mit einfachen text-algorithmen wie möglich mit ASCII. In diesem UTF-8 ist nicht schlechter als jede andere Unicode-Codierung. In der Tat kann es betrachtet werden, um besser zu sein, weil die multi-code-unit-Darstellung in UTF-8 sind häufiger und so Fehler im code die Handhabung solcher Variablen Breite Darstellung der Zeichen werden eher bemerkt und behoben, als wenn Sie versuchen zu bleiben, UTF-32 mit NFC oder NFKC.
Viele Plattformen verwenden UTF-8 als Muttersprache char-Codierung und viele Programme erfordern keine wichtigen text-Verarbeitung und-so schreibt ein Internationalisiertes Programm auf diesen Plattformen ist etwas anders als das schreiben von code ohne Berücksichtigung der Internationalisierung. Schreiben mehr weit portablen code schreiben oder auf anderen Plattformen erfordert das einfügen Umbauten an den Grenzen der APIs, die eine andere Kodierung verwenden.
Weitere alternative wird von einigen software zu wählen, eine cross-Plattform-Darstellung, wie unsigned short arrays holding UTF-16-Daten, und dann zu liefern alle der Bibliothek unterstützen und einfach zu Leben mit den Kosten, die in-Sprache-Unterstützung, etc.
C++11 fügt neue Arten der wide-Zeichen, die als alternativen zu wchar_t, char16_t und char32_t mit Telefonzentrale Sprache/Bibliothek-Funktionen. Sind diese nicht wirklich garantiert werden, UTF-16 und UTF-32, aber ich denke nicht, dass irgendein major-Implementierung ist etwas anderes. C++11 verbessert auch die UTF-8-Unterstützung, zum Beispiel mit UTF-8-string-Literale, so wird es nicht notwendig sein trick VC++ in die Herstellung von UTF-8-kodierte strings (ich kann zwar auch weiterhin tun, anstatt die
u8
Präfix).Alternativen zu vermeiden
TCHAR: TCHAR ist für die Migration von alten Windows-Programmen, die davon ausgehen legacy-Kodierungen von char zu wchar_t, und am besten vergessen, es sei denn, Ihr Programm geschrieben wurde in einigen vorherigen Jahrtausend. Es ist nicht tragbar und ist naturgemäß unspezifisch über seine Kodierung und sogar seine Daten zu geben, machen es unbrauchbar für alle nicht-TCHAR basierte API. Da sein Zweck ist es, migration zu "wchar_t", die wir haben oben gesehen, ist keine gute Idee, es gibt gar keinen Wert in mit TCHAR.
1. Zeichen, die darstellbar sind in wchar_t-strings, aber die sind nicht unterstützt in jeder beliebigen Sprache sind nicht erforderlich, vertreten zu sein mit einem einzigen wchar_t Wert. Dies bedeutet, dass wchar_t könnte ein variabler Breite Codierung für bestimmte Zeichen, ein weiterer klarer Verstoß gegen die Absicht von "wchar_t". Es ist zwar vertretbar, dass ein Charakter wird, darstellbar durch wchar_t ist genug zu sagen, dass das Gebietsschema 'unterstützt', das Zeichen, in dem Fall variabler Breite Kodierungen sind nicht legal und Fenster ist die Verwendung von UTF-16 ist non-konform.
2. Unicode erlaubt, viele Zeichen zu vertreten mit mehreren code-points, die die gleichen Probleme schafft für einfache text-algorithmen als variabler Breite Codierungen. Auch wenn man streng pflegt eine komponierte Normalisierung, einige Zeichen benötigen noch mehrere code-Punkte. Siehe: http://www.unicode.org/standard/where/
InformationsquelleAutor der Antwort
Gibt es nichts "falsch" mit "wchar_t". Das problem ist, dass, zurück in der NT-3.x Tage, Microsoft beschlossen, dass Unicode-war Gut (es ist) und für die Umsetzung von Unicode als 16-bit -, wchar_t Zeichen. So sind die meisten Microsoft-Literatur von der Mitte-90 ' s so ziemlich gleichgesetzt Unicode == utf16 == wchar_t.
Die leider nicht bei allen der Fall. "Große Zeichen" sind nicht unbedingt 2 bytes, die auf allen Plattformen und unter allen Umständen.
Dies ist einer der besten Zündkapseln auf "Unicode" (unabhängig von dieser Frage, unabhängig von C++), die ich je gesehen habe: ich hoch empfehlen:
Und ganz ehrlich, ich glaube, der beste Weg, um mit "8-bit-ASCII" vs "Win32-wide-Zeichen" vs "wchar_t-in-general" ist einfach zu akzeptieren, dass "Windows ist Anders" ... und den code entsprechend.
IMHO...
PS:
Ich bin völlig einverstanden mit jamesdlin oben:
InformationsquelleAutor der Antwort paulsm4
Pflichtlektüre:
Das Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
Wenn Sie das Programm in Java-oder .Netto - (VB.Net oder C#) - es ist weitgehend ein nicht-Problem: beide sind standardmäßig im Unicode-Format. Wenn Sie das Programm in der "klassischen" Win32-API), Ihre beste Wette ist wahrscheinlich zu verwenden TCHAR und _T() Makros (statt ausdrücklich die Verwendung wchar).
Alle Microsoft-Compiler VS2005 und später, glaube ich, standardmäßig auf 16-bit für C/C++ sowieso (Teil der Grund, warum ich immer noch mit MSVS 6.0 immer wenn ich kann ;)).
Einem anderen gute (wenn auch etwas veraltet, link):
InformationsquelleAutor der Antwort paulsm4