Актуален ли ТЧАР?

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
87
0
39 377
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Да, конечно; по крайней мере, для макроса _T. Однако я не уверен в том, что такое широкие символы.

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

WinCE использует 16-битные строки wchar_t точно так же, как Win32. У нас есть большая база кода, работающего на WinCE и Win32, и мы никогда не используем TCHAR.

mhenry1384 22.06.2010 01:30

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

Тем не мение...

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

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

arke 11.03.2010 02:34

Я сомневаюсь, что Windows когда-нибудь перейдет на UTF-32.

dan04 22.10.2012 17:50

-1 для рекомендации UTF-16. Это не только создает непереносимый (ориентированный на окна) код, что неприемлемо для библиотек - хотя может использоваться для простейших случаев, таких как код пользовательского интерфейса - это неэффективно даже в самой Windows. utf8everywhere.org

Pavel Radzivilovsky 01.11.2012 09:58
Ответ принят как подходящий

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

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

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

В самом деле, это то, что по-прежнему будет работать, когда кодировка символов в конечном итоге изменится «снова».

Medinoc 16.09.2014 18:21

Вы предпочитаете код, который явно указывает на тип символа, и поэтому используете тип, который иногда бывает таким, а иногда тем? Очень убедительно.

Deduplicator 13.01.2015 07:20
−1 для несоответствия, отмеченного @Deduplicator, и для рекомендации по отрицательной выплате использовать макрос, который может быть любым (и, как правило, не будет проверяться более чем для одного конкретного значения).
Cheers and hth. - Alf 06.07.2016 20:57

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

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

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

Интересный факт: UTF-16 не всегда присутствовал на платформе NT. Суррогатные кодовые точки были введены в Unicode 2.0 в 1996 году, в том же году, когда был выпущен NT 4. Вплоть до IIRC (включая) Windows 2000 все версии NT использовали UCS-2, фактически подмножество UTF-16, которое предполагало, что каждый символ может быть представлен одной кодовой точкой (то есть без суррогатов).

0xC0000022L 12.07.2012 20:00

Кстати, хотя я согласен с тем, что TCHAR больше не следует использовать, я не согласен с тем, что это была плохая идея. Я также думаю, что если вы выбираете явным образом вместо использования TCHAR, вы должны быть явным везде. Т.е. также не используйте функции с TCHAR / _TCHAR (например, _tmain) в их объявлении. Проще говоря: будьте последовательны. +1, все еще.

0xC0000022L 12.07.2012 20:03

Это была хорошая идея, когда он был представлен, но он не должен иметь значения в новом коде.

Adrian McCarthy 04.12.2013 21:36

Вы неверно представляете, для чего изначально были введены TCHAR: для облегчения разработки кода для версий Windows на базе Win 9x и Windows NT. В то время реализация UTF-16 в Windows NT была UCS-2, и алгоритмы синтаксического анализа / обработки строк были идентичными. Суррогатов не было. И даже с суррогатами алгоритмы для DBCS (единственная поддерживаемая кодировка MBCS для Windows) и UTF-16 одинаковы: в любой кодировке кодовая точка состоит из одной или двух кодовых единиц.

IInspectable 21.11.2015 19:15

Предположим, я хочу использовать FormatMessage () для преобразования значения из WSAGetLastError () во что-то пригодное для печати. В документации к WSAGetLastError () говорится, что он принимает LPTSTR в качестве указателя на буфер. У меня действительно нет другого выбора, кроме как использовать TCHAR, не так ли?

Edward Falk 04.08.2016 11:01

@EdwardFalk: WSAGetLastError не принимает никаких аргументов, поэтому я предполагаю, что вы имеете в виду FormatMessage. Как указано в документации, существует экспорт в Unicode, FormatMessageW, для которого требуется LPWSTR. Нет необходимости использовать сопоставления универсального текста. Это верно почти для всех вызовов Windows API, которые принимают строковые аргументы.

IInspectable 02.12.2016 16:18

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

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

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

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

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

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

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

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

Ваше приложение не использует Интернет

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

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

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

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

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

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

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

Звонок 2012 года: есть еще приложения, которые нужно обслуживать без #define _UNICODE даже сейчас. Конец передачи :)

0xC0000022L 12.07.2012 19:57

@ 0xC0000022L вопрос касался кода новый. Когда вы поддерживаете старый код, вам, очевидно, придется работать в среде, для которой написан код который. Если вы поддерживаете приложение COBOL, то не имеет значения, является ли COBOL хорошим языком или нет, вы застряли на нем. И если вы поддерживаете приложение, которое полагается на TCHAR, тогда не имеет значения, было ли это хорошее решение или нет, вы застряли на нем.

jalf 21.10.2012 13:01

Действительно, TCHAR бесполезен, кроме COBOL)

Pavel Radzivilovsky 01.11.2012 10:01
_UNICODE управляет тем, как сопоставления универсального текста разрешаются в CRT. Если вы не хотите вызывать ANSI-версию Windows API, вам необходимо определить UNICODE.
IInspectable 06.07.2016 21:45

Просто добавлю к старому вопросу:

НЕТ

Начните новый проект CLR C++ в VS2010. Сами Microsoft используют L"Hello World", - сказал Нуфф.

Среда CLR сильно отличается от неуправляемого кода. Это аргумент нет.

Cody Gray 11.06.2011 14:44

Даже Microsoft делает ошибки.

Pavel Radzivilovsky 01.11.2012 10:18

-1 Вопрос помечен как C и C++. Ответы всегда могут быть удалены их соответствующими авторами. Сейчас хорошее время, чтобы воспользоваться этим положением.

IInspectable 04.01.2013 01:05

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

New applications should always call the Unicode versions (of the API).

The TEXT and TCHAR macros are less useful today, because all applications should use Unicode.

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

Стивен, вы цитируете текст, написанный кем-то, кто не понимает значения слова «Юникод». Это один из тех досадных документов времен неразберихи с UCS-2.

Pavel Radzivilovsky 01.11.2012 10:03

@PavelRadzivilovsky: Документ был написан для системы, где Юникод и UTF-16LE обычно используются как взаимозаменяемые. Хотя это технически неточно, но, тем не менее, однозначно. Это также явно указано во введении к тому же тексту: «Windows представляет символы Unicode с использованием кодировки UTF-16 [...]».

IInspectable 02.12.2016 16:35

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

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

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

Unicode имеет как минимум три текущих кодировки (UTF-8, UTF-16, UTF-32) и одну устаревшую кодировку (UCS-2, подмножество того, что сейчас называется UTF-16). К какому из них вы относитесь? Мне нравятся остальные предложения, хотя +1

0xC0000022L 12.07.2012 19:55

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

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

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

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

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

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

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

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

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

@PavelRadzivilovsky, при реализации вашего предложения в приложении VC++, установим ли мы для символа VC++ значение «None» или «Multibyte (MBCS)»? Причина, по которой я спрашиваю, заключается в том, что я только что установил Boost :: Locale, а набором символов по умолчанию был MBCS. FWIW, мое чистое приложение ASCII было установлено на «Нет», и я теперь установил его на «MBCS» (так как я буду использовать в нем Boost :: Locale), и оно работает нормально. Пожалуйста, порекомендуйте.

Caroline Beltran 22.09.2014 03:04

Как рекомендует utf8everywhere, я бы установил для него значение «Использовать набор символов Unicode». Это рекламирует дополнительную безопасность, но не требуется. Автор Boost :: locale очень умный парень, но я уверен, что он поступил правильно.

Pavel Radzivilovsky 22.09.2014 18:52

Мантра UTF-8 везде не станет правильным решением только потому, что ее повторяют чаще. UTF-8, несомненно, является привлекательной кодировкой для сериализации (например, файлов или сетевых сокетов), но в Windows часто более уместно хранить символьные данные, используя внутреннюю кодировку UTF-16, и преобразовывать на границе приложения. Одна из причин заключается в том, что UTF-16 - единственная кодировка, которая может быть немедленно преобразована в любую другую поддерживаемую кодировку. Это не относится к UTF-8.

IInspectable 02.12.2016 16:52

«..UTF-16 - единственная кодировка, которая может быть немедленно преобразована в любую другую поддерживаемую кодировку». что ты имеешь в виду? В чем проблема с преобразованием кодировки UTF-8 во что-нибудь еще?

Pavel Radzivilovsky 03.12.2016 13:30

@PavelRadzivilovsky: «В чем проблема с преобразованием кодировки UTF-8 во что-нибудь еще?» - Я не это сказал. Вы можете сразу преобразовать UTF-8 в UTF-16, вызвав MultiByteToWideChar. Но вы не можете преобразовать из UTF-8 во что-либо еще без предварительного преобразования в UTF-16.

IInspectable 05.12.2016 22:06

Я не понимаю. К чему-нибудь еще - какому? Например. ПСК-4? Почему нет? Кажется очень простым, полностью числовой алгоритм ..

Pavel Radzivilovsky 09.12.2016 21:58

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 в качестве внутренней кодировки и хранить тексты в строках char или std :: string. И скрыть их в UTF-16 при вызове WinAPI. UTF-8 сейчас является доминирующей кодировкой, и существует множество удобных библиотек и инструментов для обработки строк UTF-8.

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

«UTF-8 теперь является доминирующей кодировкой» - Это пошло не так, поскольку вторая часть цитаты ("для всемирной паутины") не учитывалась. Для настольных приложений наиболее часто используемой собственной кодировкой символов по-прежнему является UTF-16. Его использует Windows, Mac OS X, строковые типы .NET и Java. Это составляет массивный количество кода. Не поймите меня неправильно, в UTF-8 для сериализации нет ничего плохого. Но чаще всего (особенно в Windows) вы обнаружите, что внутреннее использование UTF-16 более уместно.
IInspectable 07.12.2016 18:03

TCHAR имеют новое значение для переноса с WCHAR на CHAR.

https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/use-utf8-code-page

Recent releases of Windows 10 have used the ANSI code page and -A APIs as a means to introduce UTF-8 support to apps. If the ANSI code page is configured for UTF-8, -A APIs operate in UTF-8.

Другие вопросы по теме