web-dev-qa-db-fra.com

TCHAR est-il toujours pertinent?

Je suis nouveau dans la programmation Windows et après avoir lu le livre Petzold, je me demande:

est-ce toujours une bonne pratique d'utiliser le type TCHAR et la fonction _T() pour déclarer des chaînes ou si je devais simplement utiliser le wchar_t et L"" chaînes dans le nouveau code?

Je ne viserai que Windows 2000 et plus et mon code sera i18n dès le démarrage.

86
Fábio

J'utiliserais toujours la syntaxe TCHAR si je faisais un nouveau projet aujourd'hui. Il n'y a pas beaucoup de différence pratique entre son utilisation et la syntaxe WCHAR, et je préfère un code explicite dans le type de caractère. Étant donné que la plupart des fonctions API et des objets d'assistance prennent/utilisent des types TCHAR (par exemple: CString), il est logique de l'utiliser. De plus, il vous donne de la flexibilité si vous décidez d'utiliser le code dans une application ASCII à un moment donné, ou si Windows évolue vers Unicode32, etc.

Si vous décidez d'emprunter la route WCHAR, je serais explicite à ce sujet. Autrement dit, utilisez CStringW au lieu de CString et transformez des macros lors de la conversion en TCHAR (par exemple: CW2CT).

C'est mon avis, de toute façon.

15
Nick

La réponse courte: [~ # ~] non [~ # ~] .

Comme tous les autres ont déjà écrit, beaucoup de programmeurs utilisent encore TCHARs et les fonctions correspondantes. À mon humble avis l'ensemble du concept était une mauvaise idée . TF-16 le traitement des chaînes est très différent du simple traitement des chaînes ASCII/MBCS. Si vous utilisez les mêmes algorithmes/fonctions avec les deux (c'est ce sur quoi repose l'idée de TCHAR!), Vous obtenez de très mauvaises performances sur la version UTF-16 si vous faites un peu plus qu'une simple concaténation de chaînes (comme analyse, etc.). La raison principale est Surrogates .

À la seule exception quand vous devez vraiment compiler votre application pour un système qui ne prend pas en charge Unicode, je ne vois aucune raison d'utiliser ce bagage du passé dans une nouvelle application.

89
Sascha

Je dois être d'accord avec Sascha. La prémisse sous-jacente de TCHAR/_T()/etc. est que vous pouvez écrire une application basée sur "ANSI", puis lui donner par magie la prise en charge Unicode en définissant une macro. Mais cela est basé sur plusieurs mauvaises hypothèses:

Que vous construisez activement les versions MBCS et Unicode de votre logiciel

Sinon, vous le ferez vous glissez et utilisez l'ordinaire char* chaînes dans de nombreux endroits.

Que vous n'utilisez pas d'échappements antislash non ASCII dans les littéraux _T ("...")

À moins que votre codage "ANSI" ne soit ISO-8859-1, le char* et wchar_t* les littéraux ne représenteront pas les mêmes caractères.

Les chaînes UTF-16 sont utilisées comme les chaînes "ANSI"

Ils ne sont pas. Unicode introduit plusieurs concepts qui n'existent pas dans la plupart des encodages de caractères hérités. Surrogates. Combinaison de caractères. Normalisation. Règles de casse conditionnelles et sensibles à la langue.

Et peut-être plus important encore, le fait que UTF-16 est rarement enregistré sur disque ou envoyé sur Internet: UTF-8 a tendance à être préféré pour la représentation externe.

Que votre application n'utilise pas Internet

(Maintenant, cela peut être une hypothèse valable pour votre logiciel, mais ...)

Le Web fonctionne sur UTF-8 et ne pléthore d'encodages plus rares . Le concept TCHAR n'en reconnaît que deux: "ANSI" (qui ne peut pas être UTF-8 ) et "Unicode" (UTF-16) . Il peut être utile pour rendre vos appels d'API Windows compatibles avec Unicode, mais il est sacrément inutile pour rendre vos applications Web et de messagerie compatibles avec Unicode.

Que vous n'utilisez aucune bibliothèque non Microsoft

Personne d'autre n'utilise TCHAR. Poco utilise std::string et UTF-8. SQLite a les versions UTF-8 et UTF-16 de son API, mais pas TCHAR. TCHAR n'est même pas dans la bibliothèque standard, donc pas de std::tcout sauf si vous souhaitez le définir vous-même.

Ce que je recommande au lieu de TCHAR

Oubliez que les encodages "ANSI" existent, sauf lorsque vous devez lire un fichier qui n'est pas UTF-8 valide. Oubliez aussi TCHAR. Appelez toujours la version "W" des fonctions de l'API Windows. #define _UNICODE juste pour être sûr de ne pas appeler accidentellement une fonction "A".

Utilisez toujours les encodages UTF pour les chaînes: UTF-8 pour les chaînes char et UTF-16 (sous Windows) ou UTF-32 (sur les systèmes de type Unix) pour wchar_t chaînes. typedefUTF16 et UTF32 types de caractères pour éviter les différences de plate-forme.

77
dan04

Si vous vous demandez si c'est encore en pratique, alors oui - il est toujours utilisé un peu. Personne ne regardera votre code de façon amusante s'il utilise TCHAR et _T (""). Le projet sur lequel je travaille maintenant est la conversion d'ANSI en unicode - et nous allons sur la route portable (TCHAR).

Cependant ...

Mon vote serait d'oublier toutes les macros portables ANSI/UNICODE (TCHAR, _T (""), et tous les appels _tXXXXXX, etc ...) et de supposer unicode partout. Je ne vois vraiment pas l'intérêt d'être portable si vous n'avez jamais besoin d'une version ANSI. J'utiliserais directement toutes les fonctions et types de caractères larges. Faites précéder tous les littéraux de chaîne d'un L.

18
Aardvark

Introduction à l'article de programmation Windows sur MSDN dit

Les nouvelles applications doivent toujours appeler les versions Unicode (de l'API).

Le texte [~ # ~] [~ # ~] et [~ # ~] tchar [~ # ~ ] les macros sont moins utiles aujourd'hui, car toutes les applications devraient utiliser Unicode.

Je m'en tiendrai à wchar_t et L"".

11
Steven

Je voudrais suggérer une approche différente (aucune des deux).

Pour résumer, utilisez char * et std :: string, en supposant le codage UTF-8, et effectuez les conversions en UTF-16 uniquement lors de l'encapsulation des fonctions API.

Plus d'informations et de justification de cette approche dans les programmes Windows peuvent être trouvées dans http://www.utf8everywhere.org .

10
Pavel Radzivilovsky

TCHAR/WCHAR peut être suffisant pour certains projets hérités. Mais pour les nouvelles applications, je dirais [~ # ~] non [~ # ~] .

Tous ces TCHAR/WCHAR sont là pour des raisons historiques. TCHAR fournit un moyen (déguisement) apparemment soigné de basculer entre le codage de texte ANSI (MBCS) et le codage de texte Unicode (UTF-16). Dans le passé, les gens ne comprenaient pas le nombre de caractères de toutes les langues du monde. Ils ont supposé que 2 octets étaient suffisants pour représenter tous les caractères et donc avoir un schéma de codage de caractères de longueur fixe utilisant WCHAR. Cependant, cela n'est plus vrai après la sortie d'Unicode 2.0 en 1996 .

C'est-à-dire: peu importe ce que vous utilisez dans CHAR/WCHAR/TCHAR, la partie de traitement de texte de votre programme devrait être capable de gérer caractères de longueur variable pour l'internationalisation.

Donc, vous devez en fait faire plus que d'en choisir un parmi CHAR/WCHAR/TCHAR pour la programmation sous Windows:

  1. Si votre application est petite et n'implique pas de traitement de texte (c'est-à-dire de simplement passer la chaîne de texte comme arguments), alors restez avec WCHAR. Comme il est plus facile de travailler avec WinAPI avec le support Unicode.
  2. Sinon, je suggère d'utiliser UTF-8 comme encodage interne et de stocker les textes dans des chaînes de caractères ou std :: string. Et convertissez-les en UTF-16 lorsque vous appelez WinAPI. TF-8 est maintenant l'encodage dominant et il existe de nombreuses bibliothèques et outils pratiques pour traiter les chaînes UTF-8.

Consultez ce merveilleux site Web pour une lecture plus approfondie: http://utf8everywhere.org/

6
LeOpArD

Oui absolument; au moins pour la macro _T. Cependant, je ne suis pas sûr des trucs à caractère large.

La raison en est de mieux prendre en charge WinCE ou d'autres plates-formes Windows non standard. Si vous êtes certain à 100% que votre code restera sur NT, vous pouvez probablement simplement utiliser des déclarations de chaîne C régulières. Cependant, il est préférable de tendre vers l'approche plus flexible, car il est beaucoup plus facile de # définir cette macro sur une plate-forme non Windows par rapport à parcourir des milliers de lignes de code et à l'ajouter partout au cas où vous auriez besoin de porter une bibliothèque à Windows Mobile.

4
Nik Reiman

Les seules raisons pour lesquelles je vois utiliser autre chose que le WCHAR explicite sont la portabilité et l'efficacité.

Si vous voulez rendre votre exécutable final aussi petit que possible, utilisez char.

Si vous ne vous souciez pas de l'utilisation de RAM et que l'internationalisation soit aussi simple qu'une simple traduction, utilisez WCHAR.

Si vous souhaitez rendre votre code flexible, utilisez TCHAR.

Si vous prévoyez uniquement d'utiliser les caractères latins, vous pouvez aussi bien utiliser les chaînes ASCII/MBCS afin que votre utilisateur n'ait pas besoin d'autant de RAM.

Pour les personnes qui sont "i18n dès le démarrage", enregistrez-vous l'espace du code source et utilisez simplement toutes les fonctions Unicode.

2
Trololol

À mon humble avis, s'il y a des TCHAR dans votre code, vous travaillez au mauvais niveau d'abstraction.

Utiliser peu importe le type de chaîne est le plus pratique pour vous lorsque vous traitez le traitement de texte - ce sera, espérons-le, quelque chose qui prend en charge l'unicode, mais cela dépend de vous. Effectuez la conversion aux limites de l'API OS si nécessaire.

Lorsque vous traitez des chemins de fichiers, créez votre propre type personnalisé au lieu d'utiliser des chaînes. Cela vous permettra des séparateurs de chemin indépendants du système d'exploitation, vous donnera une interface plus facile à coder que la concaténation et la division de chaînes manuelles, et sera beaucoup plus facile à adapter à différents systèmes d'exploitation (ansi, ucs-2, utf-8, peu importe) .

2
snemarch