TCHAR все еще актуален? - PullRequest
       72

TCHAR все еще актуален?

85 голосов
/ 24 октября 2008

Я новичок в программировании Windows, и после прочтения книги Петцольда мне интересно:

Является ли все еще хорошей практикой использование типа TCHAR и функции _T() для объявления строк или если мне просто нужно использовать строки wchar_t и L"" в новом коде?

Я буду ориентироваться только на Windows 2000 и выше, и мой код будет i18n с момента запуска.

Ответы [ 11 ]

88 голосов
/ 26 ноября 2008

Краткий ответ: НЕТ .

Как и все другие, уже написанные, многие программисты все еще используют TCHAR и соответствующие функции. По моему скромному мнению вся концепция была плохой идеей . UTF-16 обработка строк сильно отличается от простой обработки строк ASCII / MBCS. Если вы используете одни и те же алгоритмы / функции с ними обоими (на этом основана идея TCHAR!), Вы получите очень плохую производительность в версии UTF-16, если вы делаете немного больше, чем простая конкатенация строк (например разбор и т. д.). Основной причиной являются суррогаты .

За единственным исключением, когда вы действительно должны скомпилировать ваше приложение для системы, которая не поддерживает Unicode, я не вижу причин использовать этот багаж из прошлого в новом приложении.

77 голосов
/ 09 июня 2010

Я должен согласиться с Сашей. Исходная предпосылка TCHAR / _T() / и т. Д. Заключается в том, что вы можете написать приложение на основе «ANSI» и затем волшебным образом дать ему поддержку Unicode, определив макрос. Но это основано на нескольких неправильных предположениях:

что вы активно создаете версии программного обеспечения для MBCS и Unicode

В противном случае вы будете проскальзывать и использовать обычные строки char* во многих местах.

То, что вы не используете экранирование без обратной ASCII в литералах _T ("...")

Если ваша кодировка "ANSI" не соответствует ISO-8859-1, результирующие литералы char* и wchar_t* не будут представлять одинаковые символы.

что строки UTF-16 используются так же, как строки "ANSI"

Это не так. Юникод вводит несколько концепций, которых нет в большинстве устаревших кодировок символов. Суррогаты. Сочетание персонажей. Нормализация. Условные и языковые правила обсадных труб.

И, возможно, самое главное, тот факт, что UTF-16 редко сохраняется на диске или отправляется через Интернет: UTF-8 имеет тенденцию быть предпочтительным для внешнего представления.

То, что ваше приложение не использует Интернет

(Теперь это может быть верным предположением для вашего программного обеспечения, но ...)

Сеть работает на UTF-8 и множестве более редких кодировок . Концепция TCHAR распознает только два: «ANSI» (который не может быть UTF-8 ) и «Unicode» (UTF-16). Это может быть полезно для того, чтобы ваши вызовы Windows API поддерживали Unicode, но чертовски бесполезны для того, чтобы сделать ваши веб-приложения и почтовые приложения поддерживающими Unicode.

То, что вы не используете библиотеки сторонних разработчиков

Никто другой не использует TCHAR. Poco использует std::string и UTF-8. SQLite имеет версии API UTF-8 и UTF-16, но не TCHAR. TCHAR нет даже в стандартной библиотеке, поэтому нет std::tcout, если вы не хотите определить его самостоятельно.

Что я рекомендую вместо TCHAR

Забудьте, что существуют кодировки «ANSI», за исключением случаев, когда вам нужно прочитать файл, который не является допустимым UTF-8. Забудьте о TCHAR тоже. Всегда вызывайте "W" версию функций Windows API. #define _UNICODE просто чтобы убедиться, что вы случайно не вызвали функцию "A".

Всегда используйте кодировки UTF для строк: UTF-8 для строк char и UTF-16 (в Windows) или UTF-32 (в Unix-подобных системах) для строк wchar_t. typedef UTF16 и UTF32 типы символов, чтобы избежать различий между платформами.

18 голосов
/ 24 октября 2008

Если вам интересно, по-прежнему ли это на практике, тогда да - он все еще используется довольно часто. Никто не посмотрит на ваш код смешно, если он использует TCHAR и _T (""). Проект, над которым я сейчас работаю, - это преобразование из ANSI в юникод, и мы собираемся использовать переносной (TCHAR) маршрут.

Однако ...

Моим голосом было бы забыть все переносимые макросы ANSI / UNICODE (TCHAR, _T ("") и все вызовы _tXXXXXX и т. Д. ...) и просто использовать везде юникод. Я действительно не вижу смысла в переносимости, если вам никогда не понадобится версия ANSI. Я бы использовал все функции и типы широких символов напрямую. Предварительно предваряйте все строковые литералы символом L.

15 голосов
/ 24 октября 2008

Я бы все еще использовал синтаксис TCHAR, если бы сегодня делал новый проект. Между его использованием и синтаксисом WCHAR нет большой практической разницы, и я предпочитаю код, который явно указан в типе символа. Поскольку большинство функций API и вспомогательных объектов принимают / используют типы TCHAR (например, CString), имеет смысл использовать его. Кроме того, это дает вам гибкость, если вы решите использовать код в приложении ASCII в какой-то момент или если Windows когда-либо перейдет на Unicode32 и т. Д.

Если вы решите пойти по маршруту WCHAR, я бы прямо об этом сказал. То есть используйте CStringW вместо CString и применяйте макросы при преобразовании в TCHAR (например, CW2CT).

Во всяком случае, это мое мнение.

11 голосов
/ 14 августа 2010

В статье Введение в программирование Windows на MSDN написано

Новые приложения должны всегда вызывать версии Unicode (API).

Макросы TEXT и TCHAR сегодня менее полезны, поскольку все приложения должны использовать Unicode.

Я бы придерживался wchar_t и L"".

10 голосов
/ 24 января 2012

Я хотел бы предложить другой подход (ни один из двух).

Для суммирования используйте char * и std :: string, предполагая кодировку UTF-8, и выполняйте преобразования в UTF-16 только при переносе функций API.

Дополнительную информацию и обоснование этого подхода в программах Windows можно найти в http://www.utf8everywhere.org.

6 голосов
/ 15 марта 2015

TCHAR / WCHAR может быть достаточно для некоторых устаревших проектов. Но для новых приложений я бы сказал НЕТ .

Все эти вещи TCHAR / WCHAR существуют по историческим причинам. TCHAR обеспечивает, казалось бы, аккуратный способ (маскировка) для переключения между кодировкой текста ANSI (MBCS) и кодировкой текста Unicode (UTF-16). В прошлом у людей не было понимания количества символов всех языков мира. Они предполагали, что 2 байта было достаточно для представления всех символов и, таким образом, имели схему кодирования символов фиксированной длины с использованием WCHAR. Однако, это больше не верно после выпуска Unicode 2.0 в 1996 .

То есть: Независимо от того, что вы используете в CHAR / WCHAR / TCHAR, часть обработки текста в вашей программе должна обрабатывать символов переменной длины для интернационализации.

Так что вам действительно нужно сделать больше, чем выбрать один из CHAR / WCHAR / TCHAR для программирования в Windows:

  1. Если ваше приложение невелико и не требует обработки текста (т.е. просто передает текстовую строку в качестве аргументов), тогда придерживайтесь WCHAR. Так как этот способ проще работать с WinAPI с поддержкой Unicode.
  2. В противном случае я бы предложил использовать UTF-8 в качестве внутренней кодировки и хранить тексты в символьных строках или std :: string. И скрыть их в UTF-16 при вызове WinAPI. UTF-8 теперь является доминирующей кодировкой, и существует множество удобных библиотек и инструментов для обработки строк UTF-8.

Посетите этот замечательный веб-сайт для более глубокого прочтения: http://utf8everywhere.org/

4 голосов
/ 24 октября 2008

Да, абсолютно; по крайней мере для макроса _T. Я не очень уверен насчет широких персонажей.

Причина в том, что лучше поддерживать WinCE или другие нестандартные платформы Windows. Если вы на 100% уверены, что ваш код останется в NT, то вы, вероятно, можете просто использовать обычные объявления C-строк. Тем не менее, лучше стремиться к более гибкому подходу, так как гораздо проще определить этот макрос на платформе, отличной от Windows, по сравнению с просмотром тысяч строк кода и добавлением его везде, если вам нужно портировать какую-то библиотеку для Windows Mobile.

2 голосов
/ 06 января 2012

Единственными причинами, по которым я вижу использование чего-либо, кроме явного WCHAR, являются мобильность и эффективность.

Если вы хотите, чтобы ваш окончательный исполняемый файл был как можно меньше, используйте char.

Если вы не заботитесь об использовании оперативной памяти и хотите, чтобы интернационализация была такой же простой, как и простой перевод, используйте WCHAR.

Если вы хотите сделать свой код гибким, используйте TCHAR.

Если вы планируете использовать только латинские символы, вы также можете использовать строки ASCII / MBCS, чтобы вашему пользователю не требовалось столько ОЗУ.

Для людей, которые «i18n с самого начала», сохраните пространство исходного кода и просто используйте все функции Unicode.

2 голосов
/ 26 августа 2010

ИМХО, если в вашем коде есть TCHAR, вы работаете на неправильном уровне абстракции.

Используйте независимо от того, какой тип строки наиболее удобен для вас при работе с текстовой обработкой - надеюсь, это будет что-то, поддерживающее юникод, но это зависит от вас. При необходимости выполните преобразование на границах API ОС.

При работе с путями к файлам, вместо использования строк создайте свой собственный тип. Это позволит вам независимые от ОС разделители путей, даст вам более простой интерфейс для кодирования, чем ручная конкатенация и разбиение строк, и будет намного легче адаптироваться к различным ОС (ansi, ucs-2, utf-8, что угодно) .

...