Ich bin neu in der Windows-Programmierung und nachdem ich das Petzold-Buch gelesen habe, frage ich mich:
ist es immer noch gute Praxis, die zu verwenden TCHAR Typ und die _T() Funktion zum Deklarieren von Strings oder ob ich nur die verwenden sollte wchar_t und L"" Zeichenfolgen in neuem Code?
Ich werde nur auf Windows 2000 und höher abzielen, und mein Code wird sein i18n von Anfang an.
Sascha
Die kurze Antwort: NEIN.
Wie alle anderen bereits geschrieben haben, verwenden viele Programmierer immer noch TCHARs und die entsprechenden Funktionen. Meiner bescheidenen Meinung nach Das ganze Konzept war eine schlechte Idee. UTF-16 Die String-Verarbeitung unterscheidet sich stark von der einfachen ASCII/MBCS-String-Verarbeitung. Wenn Sie mit beiden dieselben Algorithmen/Funktionen verwenden (darauf basiert die TCHAR-Idee!), erhalten Sie eine sehr schlechte Leistung in der UTF-16-Version, wenn Sie etwas mehr als eine einfache Zeichenfolgenverkettung (wie z parsen usw.). Der Hauptgrund sind Ersatz.
Mit der einzigen Ausnahme, wenn Sie Ja wirklich Ihre Anwendung für ein System kompilieren müssen, das Unicode nicht unterstützt. Ich sehe keinen Grund, diesen Ballast aus der Vergangenheit in einer neuen Anwendung zu verwenden.
Fun Fact: UTF-16 war auf der NT-Plattform nicht immer vorhanden. Ersatzcodepunkte wurden 1996 mit Unicode 2.0 eingeführt, im selben Jahr, in dem NT 4 veröffentlicht wurde. Bis IIRC (einschließlich) Windows 2000 verwendeten alle NT-Versionen UCS-2, effektiv eine Teilmenge von UTF-16, die davon ausging, dass jedes Zeichen mit einem Codepunkt darstellbar ist (dh keine Ersatzzeichen).
– 0xC0000022L
12. Juli 2012 um 16:00 Uhr
btw, obwohl ich dem zustimme TCHAR nicht mehr verwendet werden sollte, bin ich nicht der Meinung, dass dies eine schlechte Idee war. ich denke das auch wenn Sie entscheiden sich dafür, explizit zu sein, anstatt zu verwenden TCHAR du solltest explizit sein überall, überallhin, allerorts. Dh keine Funktionen mit verwenden TCHAR/_TCHAR (wie zum Beispiel _tmain) in ihrer Erklärung auch nicht. Einfach gesagt: Seien Sie konsequent. +1, immer noch.
– 0xC0000022L
12. Juli 2012 um 16:03 Uhr
Es war eine gute Idee zurück, als es eingeführt wurde, aber es sollte in neuem Code irrelevant sein.
– Adrian McCarthy
4. Dezember 2013 um 17:36 Uhr
Sie stellen falsch dar, was TCHARs wurden ursprünglich eingeführt für: Um die Entwicklung von Code für Win 9x- und Windows NT-basierte Versionen von Windows zu erleichtern. Zu dieser Zeit war die UTF-16-Implementierung von Windows NT UCS-2, und die Algorithmen für das Analysieren/Manipulieren von Zeichenfolgen waren identisch. Es gab keine Stellvertreter. Und selbst mit Ersatzzeichen sind die Algorithmen für DBCS (die einzige unterstützte MBCS-Codierung für Windows) und UTF-16 identisch: Bei beiden Codierungen besteht ein Codepunkt aus einer oder zwei Codeeinheiten.
– Inspektionsfähig
21. November 2015 um 16:15 Uhr
Angenommen, ich möchte FormatMessage() verwenden, um einen Wert von WSAGetLastError() in etwas Druckbares umzuwandeln. Die Dokumentation für WSAGetLastError() sagt, dass es LPTSTR als Zeiger auf den Puffer nimmt. Ich habe wirklich keine andere Wahl, als TCHAR zu verwenden, oder?
– Eduard Falk
4. August 2016 um 8:01 Uhr
dan04
Da muss ich Sascha zustimmen. Die zugrunde liegende Prämisse von TCHAR / _T() / etc. ist, dass Sie eine “ANSI”-basierte Anwendung schreiben und ihr dann auf magische Weise Unicode-Unterstützung geben können, indem Sie ein Makro definieren. Dies basiert jedoch auf mehreren schlechten Annahmen:
Dass Sie sowohl MBCS- als auch Unicode-Versionen Ihrer Software aktiv erstellen
Ansonsten du Wille ausrutschen und normal verwenden char* Saiten an vielen Stellen.
Dass Sie in _T(“…”)-Literalen keine Nicht-ASCII-Backslash-Escapezeichen verwenden
Sofern Ihre “ANSI” -Codierung nicht zufällig ISO-8859-1 ist, ist das Ergebnis char* und wchar_t* Literale repräsentieren nicht die gleichen Zeichen.
Dass UTF-16-Strings genauso wie “ANSI”-Strings verwendet werden
Sie sind nicht. Unicode führt mehrere Konzepte ein, die in den meisten älteren Zeichencodierungen nicht vorhanden sind. Ersatz. Zeichen kombinieren. Normalisierung. Bedingte und sprachabhängige Groß- und Kleinschreibung.
Und vielleicht am wichtigsten ist die Tatsache, dass UTF-16 selten auf der Festplatte gespeichert oder über das Internet gesendet wird: UTF-8 wird tendenziell für die externe Darstellung bevorzugt.
Dass Ihre Anwendung nicht das Internet verwendet
(Nun, dies kann eine gültige Annahme für sein dein software, aber…)
Das Web läuft auf UTF-8 und eine Fülle seltener Kodierungen. Die TCHAR Das Konzept kennt nur zwei: “ANSI” (was kippen B. UTF-8) und “Unicode” (UTF-16) sein. Es kann nützlich sein, um Ihre Windows-API-Aufrufe Unicode-fähig zu machen, aber es ist verdammt nutzlos, Ihre Web- und E-Mail-Apps Unicode-fähig zu machen.
Dass Sie keine Nicht-Microsoft-Bibliotheken verwenden
Niemand sonst verwendet TCHAR. Poko Verwendet std::string und UTF-8. SQLite hat UTF-8- und UTF-16-Versionen seiner API, aber nein TCHAR. TCHAR ist nicht einmal in der Standardbibliothek, also nein std::tcout Es sei denn, Sie möchten es selbst definieren.
Was ich anstelle von TCHAR empfehle
Vergessen Sie, dass “ANSI”-Kodierungen existieren, außer wenn Sie eine Datei lesen müssen, die kein gültiges UTF-8 ist. Vergessen TCHAR zu. Rufen Sie immer die “W”-Version von Windows-API-Funktionen auf. #define _UNICODE Nur um sicherzustellen, dass Sie nicht versehentlich eine “A” -Funktion aufrufen.
Verwenden Sie immer UTF-Codierungen für Zeichenfolgen: UTF-8 für char Zeichenfolgen und UTF-16 (unter Windows) oder UTF-32 (auf Unix-ähnlichen Systemen) für wchar_t Saiten. typedefUTF16 und UTF32 Zeichentypen, um Plattformunterschiede zu vermeiden.
2012 Aufruf: Es gibt noch Anwendungen ohne zu warten #define _UNICODE selbst jetzt. Ende der Übertragung 🙂
– 0xC0000022L
12. Juli 2012 um 15:57 Uhr
@ 0xC0000022L die Frage war ungefähr Neu Code. Wenn Sie alten Code pflegen, müssen Sie natürlich mit der Umgebung arbeiten das Code ist für geschrieben. Wenn Sie eine COBOL-Anwendung warten, spielt es keine Rolle, ob COBOL eine gute Sprache ist oder nicht, Sie bleiben dabei. Und wenn Sie eine Anwendung warten, die auf TCHAR angewiesen ist, spielt es keine Rolle, ob das eine gute Entscheidung war oder nicht, Sie bleiben dabei.
– jalf
21. Oktober 2012 um 9:01 Uhr
In der Tat ist TCHAR nicht nützlich, es sei denn in COBOL)
– Pavel Radzivilovsky
1. November 2012 um 6:01 Uhr
_UNICODE steuert, wie die generischen Textzuordnungen in der CRT aufgelöst werden. Wenn Sie die ANSI-Version einer Windows-API nicht aufrufen möchten, müssen Sie definieren UNICODE.
– Inspektionsfähig
6. Juli 2016 um 18:45 Uhr
Erdferkel
Wenn Sie sich fragen, ob es noch in der Praxis ist, dann ja – es wird immer noch ziemlich viel verwendet. Niemand wird Ihren Code komisch ansehen, wenn er TCHAR und _T(“”) verwendet. Das Projekt, an dem ich gerade arbeite, konvertiert von ANSI nach Unicode – und wir gehen den Weg der Portabilität (TCHAR).
Aber…
Meine Stimme wäre, alle tragbaren ANSI/UNICODE-Makros (TCHAR, _T(“”) und alle _tXXXXXX-Aufrufe usw. zu vergessen und einfach überall Unicode anzunehmen. Ich sehe wirklich keinen Sinn darin, portabel zu sein, wenn Sie niemals eine ANSI-Version benötigen. Ich würde alle Wide-Character-Funktionen und -Typen direkt verwenden. Stellen Sie allen Zeichenfolgenliteralen ein L voran.
Sie könnten einen Code schreiben, den Sie woanders verwenden möchten, wo Sie eine ANSI-Version benötigen, oder (wie Nick sagte) Windows könnte zu DCHAR oder was auch immer wechseln, also denke ich immer noch, dass es eine sehr gute Idee ist, mit TCHAR statt zu gehen WCHAR.
– Chris Walton
10. März 2010 um 23:34 Uhr
Ich bezweifle, dass Windows jemals auf UTF-32 umstellen wird.
– dan04
22. Oktober 2012 um 13:50 Uhr
-1 für UTF-16-Empfehlung. Dies erzeugt nicht nur nicht-portablen (Windows-zentrierten) Code, der für Bibliotheken nicht akzeptabel ist – auch wenn er für die einfachsten Fälle wie UI-Code verwendet werden kann – er ist nicht einmal unter Windows selbst effizient. utf8everywhere.org
– Pavel Radzivilovsky
1. November 2012 um 5:58 Uhr
Nick
Ich würde immer noch die TCHAR-Syntax verwenden, wenn ich heute ein neues Projekt machen würde. Es gibt keinen großen praktischen Unterschied zwischen der Verwendung und der WCHAR-Syntax, und ich bevorzuge Code, der den Zeichentyp explizit angibt. Da die meisten API-Funktionen und Hilfsobjekte TCHAR-Typen annehmen/verwenden (z. B.: CString), ist es einfach sinnvoll, sie zu verwenden. Außerdem gibt es Ihnen Flexibilität, wenn Sie sich irgendwann entscheiden, den Code in einer ASCII-App zu verwenden, oder wenn Windows jemals zu Unicode32 weiterentwickelt wird usw.
Wenn Sie sich für die WCHAR-Route entscheiden, würde ich das ausdrücklich sagen. Das heißt, verwenden Sie CStringW anstelle von CString und wandeln Sie Makros um, wenn Sie in TCHAR konvertieren (z. B.: CW2CT).
Neue Anwendungen sollten immer die Unicode-Versionen (der API) aufrufen.
Die TEXT und TCHAR Makros sind heute weniger nützlich, da alle Anwendungen Unicode verwenden sollten.
Ich würde mich daran halten wchar_t und L"".
Steven, Sie zitieren einen Text, der von jemandem geschrieben wurde, der die Bedeutung des Wortes „Unicode“ nicht versteht. Es ist eines dieser unglücklichen Dokumente aus der Zeit der UCS-2-Verwirrung.
– Pavel Radzivilovsky
1. November 2012 um 6:03 Uhr
@PavelRadzivilovsky: Das Dokument wurde für ein System geschrieben, in dem Unicode und UTF-16LE werden häufig synonym verwendet. Obwohl es technisch ungenau ist, ist es dennoch eindeutig. Darauf wird auch in der Einleitung desselben Textes ausdrücklich hingewiesen: „Windows stellt Unicode-Zeichen mit UTF-16-Codierung dar […]”.
– Inspektionsfähig
2. Dezember 2016 um 13:35 Uhr
Ich möchte einen anderen Ansatz vorschlagen (keiner von beiden).
Zusammenfassend verwenden Sie char* und std::string unter der Annahme einer UTF-8-Codierung, und führen Sie die Konvertierungen in UTF-16 nur beim Umschließen von API-Funktionen durch.
Weitere Informationen und Begründungen für diesen Ansatz in Windows-Programmen finden Sie in http://www.utf8everywhere.org.
Steven, Sie zitieren einen Text, der von jemandem geschrieben wurde, der die Bedeutung des Wortes „Unicode“ nicht versteht. Es ist eines dieser unglücklichen Dokumente aus der Zeit der UCS-2-Verwirrung.
– Pavel Radzivilovsky
1. November 2012 um 6:03 Uhr
@PavelRadzivilovsky: Das Dokument wurde für ein System geschrieben, in dem Unicode und UTF-16LE werden häufig synonym verwendet. Obwohl es technisch ungenau ist, ist es dennoch eindeutig. Darauf wird auch in der Einleitung desselben Textes ausdrücklich hingewiesen: „Windows stellt Unicode-Zeichen mit UTF-16-Codierung dar […]”.
– Inspektionsfähig
2. Dezember 2016 um 13:35 Uhr
StaceyGirl
TCHAR/WCHAR könnte für einige Legacy-Projekte ausreichen. Aber für neue Anwendungen, würde ich sagen NEIN.
All diese TCHAR/WCHAR Sachen gibt es aus historischen Gründen. TCHAR bietet eine scheinbar saubere Möglichkeit (Tarnung), zwischen ANSI-Textcodierung (MBCS) und Unicode-Textcodierung (UTF-16) zu wechseln. In der Vergangenheit hatten die Menschen kein Verständnis für die Anzahl der Schriftzeichen aller Sprachen der Welt. Sie gingen davon aus, dass 2 Bytes ausreichten, um alle Zeichen darzustellen und somit ein Zeichencodierungsschema mit fester Länge zu verwenden WCHAR. Dies gilt jedoch nicht mehr nach der Veröffentlichung von Unicode 2.0 in 1996.
Das heißt: Egal welche Sie verwenden CHAR/WCHAR/TCHARsollte der Textverarbeitungsteil in Ihrem Programm verarbeiten können Zeichen mit variabler Länge für die Internationalisierung.
Sie müssen also tatsächlich mehr tun, als sich für eines zu entscheiden CHAR/WCHAR/TCHAR für die Programmierung unter Windows:
Wenn Ihre Anwendung klein ist und keine Textverarbeitung beinhaltet (dh nur die Textzeichenfolge als Argumente weitergibt), dann bleiben Sie dabei WCHAR. Da es auf diese Weise einfacher ist, mit WinAPI mit Unicode-Unterstützung zu arbeiten.
Andernfalls würde ich vorschlagen, UTF-8 als interne Codierung zu verwenden und Texte in Zeichenketten oder std::string zu speichern. Und wandeln Sie sie beim Aufrufen von WinAPI in UTF-16 um. UTF-8 ist jetzt die vorherrschende Kodierung und es gibt viele praktische Bibliotheken und Tools, um UTF-8-Strings zu verarbeiten.
Schauen Sie sich diese wundervolle Website an, um mehr in die Tiefe zu lesen: http://utf8everywhere.org/
“UTF-8 ist jetzt die dominierende Codierung” – Dies wurde falsch, indem der zweite Teil des Zitats weggelassen wurde (“für das World Wide Web”). Für Desktop-Anwendungen ist die am häufigsten verwendete native Zeichenkodierung wahrscheinlich immer noch UTF-16. Windows verwendet es, Mac OS X auch und die String-Typen von .NET und Java. Das macht a aus fest Menge an Code da draußen. Verstehen Sie mich nicht falsch, an UTF-8 für die Serialisierung ist nichts auszusetzen. Aber meistens (insbesondere unter Windows) werden Sie feststellen, dass die interne Verwendung von UTF-16 angemessener ist.