TCHAR 仍然相关吗?
Posted
技术标签:
【中文标题】TCHAR 仍然相关吗?【英文标题】:Is TCHAR still relevant? 【发布时间】:2010-09-19 01:27:49 【问题描述】:我是 Windows 编程新手,在阅读 Petzold 的书后,我想知道:
使用TCHAR
类型和_T()
函数声明字符串是否仍然是一种好习惯,或者我是否应该在新代码中只使用wchar_t
和L""
字符串?
我将只针对 Windows 2000 及更高版本,我的代码从一开始就是i18n。
【问题讨论】:
【参考方案1】:是的,绝对的;至少对于 _T 宏。不过,我不太确定宽字符的东西。
原因是为了更好地支持 WinCE 或其他非标准 Windows 平台。如果您 100% 确定您的代码将保留在 NT 上,那么您可能只使用常规的 C 字符串声明。但是,最好倾向于更灵活的方法,因为在非 Windows 平台上#define 该宏要容易得多,而不是通过数千行代码并将其添加到任何地方,以防您需要移植一些库到 Windows 移动版。
【讨论】:
WinCE 使用 16 位 wchar_t 字符串,就像 Win32 一样。我们有大量在 WinCE 和 Win32 上运行的代码库,我们从不使用 TCHAR。【参考方案2】:如果您想知道它是否仍在实践中,那么是的 - 它仍然被大量使用。如果你的代码使用了 TCHAR 和 _T(""),没有人会觉得你的代码很有趣。我现在正在进行的项目正在从 ANSI 转换为 unicode - 我们正在采用可移植 (TCHAR) 路线。
但是...
我的投票是忘记所有 ANSI/UNICODE 可移植宏(TCHAR、_T("") 和所有 _tXXXXXX 调用等...),而只是假设到处都是 unicode。如果您永远不需要 ANSI 版本,我真的看不出便携的意义。我会直接使用所有宽字符函数和类型。用 L 前置所有字符串文字。
【讨论】:
您可能会编写一些您想要在需要 ANSI 版本的其他地方使用的代码,或者(正如尼克所说)Windows 可能会迁移到 DCHAR 或其他什么,所以我仍然认为这是一个非常使用 TCHAR 而不是 WCHAR 是个好主意。 我怀疑 Windows 是否会切换到 UTF-32。 -1 用于 UTF-16 推荐。这不仅会创建不可移植(以 Windows 为中心)的代码,这对于库来说是不可接受的——即使可能用于 UI 代码等最简单的情况——即使在 Windows 本身上也效率不高。 utf8everywhere.org【参考方案3】:如果我今天做一个新项目,我仍然会使用 TCHAR 语法。使用它和 WCHAR 语法之间没有太大的实际区别,我更喜欢在字符类型是什么方面明确的代码。由于大多数 API 函数和辅助对象采用/使用 TCHAR 类型(例如:CString),因此使用它才有意义。此外,如果您决定在某个时候在 ASCII 应用程序中使用代码,或者如果 Windows 曾经演变为 Unicode32 等,它会为您提供灵活性。
如果您决定走 WCHAR 路线,我会明确说明。即用CStringW代替CString,在转换为TCHAR时使用宏转换(如:CW2CT)。
无论如何,这是我的看法。
【讨论】:
确实,当字符编码最终“再次”更改时,这仍然有效。 您更喜欢明确显示字符类型的代码,因此使用有时是这个有时是那个的类型?很有说服力。 −1 用于@Deduplicator 指出的不一致性,以及使用可以是任何宏的负面回报建议(通常不会测试超过一个具体值)。【参考方案4】:简短的回答:否。
就像所有其他人已经写过的一样,很多程序员仍然使用 TCHAR 和相应的函数。在我看来整个概念是个坏主意。 UTF-16 字符串处理与简单的 ASCII/MBCS 字符串处理有很大不同。如果你对它们都使用相同的算法/函数(这是 TCHAR 想法的基础!),如果你做的不仅仅是简单的字符串连接(比如解析等)。主要原因是Surrogates。
唯一的例外是当您真的必须为不支持 Unicode 的系统编译应用程序时,我认为没有理由在新应用程序中使用过去的包袱。
【讨论】:
有趣的事实:UTF-16 在 NT 平台上并不总是存在。 1996 年,Unicode 2.0 引入了代理代码点,同年 NT 4 发布。直到,IIRC,(包括)Windows 2000 所有 NT 版本都使用 UCS-2,实际上是 UTF-16 的一个子集,它假定每个字符都可以用一个代码点表示(即没有代理)。 顺便说一句,虽然我同意不应再使用TCHAR
,但我不同意这是一个坏主意。我也认为如果你选择显式而不是使用TCHAR
你应该显式无处不在。 IE。也不要在声明中使用带有TCHAR
/_TCHAR
(例如_tmain
)的函数。简单地说:保持一致。 +1,仍然。
它在引入时是个好主意,但在新代码中应该无关紧要。
您歪曲了 TCHAR
s 最初引入的目的:简化 Win 9x 和基于 Windows NT 的 Windows 版本的代码开发。那时,Windows NT 的 UTF-16 实现是 UCS-2,字符串解析/操作的算法是相同的。没有代理人。即使使用代理,DBCS(Windows 唯一支持的 MBCS 编码)和 UTF-16 的算法也是相同的:在任何一种编码中,一个代码点都由一个或两个代码单元组成。
假设我想使用 FormatMessage() 将值从 WSAGetLastError() 转换为可打印的值。 WSAGetLastError() 的文档说它将 LPTSTR 作为指向缓冲区的指针。我真的别无选择,只能使用 TCHAR,不是吗?【参考方案5】:
我必须同意萨沙的观点。 TCHAR
/_T()
/等的基本前提是你可以编写一个基于“ANSI”的应用程序,然后通过定义一个宏神奇地赋予它Unicode支持。但这是基于几个错误的假设:
您积极构建您的软件的 MBCS 和 Unicode 版本
否则,你会犯错,在很多地方使用普通的char*
字符串。
您不在 _T("...") 文字中使用非 ASCII 反斜杠转义
除非您的“ANSI”编码恰好是 ISO-8859-1,否则生成的 char*
和 wchar_t*
文字将不会代表相同的字符。
UTF-16 字符串的使用方式与“ANSI”字符串一样
他们不是。 Unicode 引入了大多数传统字符编码中不存在的几个概念。代理人。组合字符。正常化。条件和语言敏感的大小写规则。
也许最重要的是,UTF-16 很少保存在磁盘上或通过 Internet 发送这一事实:UTF-8 往往更适合用于外部表示。
您的应用程序不使用互联网
(现在,对于你的软件来说,这可能是一个有效的假设,但是...)
The web runs on UTF-8 和 a plethora of rarer encodings。 TCHAR
概念仅识别两个:“ANSI”(can't be UTF-8)和“Unicode”(UTF-16)。它可能有助于让你的 Windows API 调用支持 Unicode,但它对于让你的 Web 和电子邮件应用程序支持 Unicode 毫无用处。
您不使用非 Microsoft 库
没有其他人使用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 编码:char
字符串使用 UTF-8,wchar_t
字符串使用 UTF-16(在 Windows 上)或 UTF-32(在类 Unix 系统上)。 typedef
UTF16
和 UTF32
字符类型以避免平台差异。
【讨论】:
2012 调用:即使是现在,在没有#define _UNICODE
的情况下仍有应用程序需要维护。传输结束:)
@0xC0000022L 问题是关于 new 代码的。当您维护旧代码时,您显然必须使用编写代码的环境。如果您正在维护 COBOL 应用程序,那么 COBOL 是否是一门好语言并不重要,您会被它困住。如果您正在维护一个依赖于 TCHAR 的应用程序,那么这是否是一个好的决定并不重要,您只能坚持下去。
确实,TCHAR 除非在 COBOL 中才有用)
_UNICODE
控制如何在 CRT 中解析通用文本映射。如果不想调用ANSI版本的Windows API,需要定义UNICODE
。【参考方案6】:
只是添加一个旧问题:
否
在 VS2010 中开始一个新的 CLR C++ 项目。微软自己使用L"Hello World"
,'nuff 说。
【讨论】:
CLR 是一个与非托管代码截然不同的环境。那是不是一个论点。 微软也会犯错。 -1 问题被标记为C
和C++
。答案总是可以被各自的作者删除。这将是使用该条款的好时机。【参考方案7】:
MSDN 上的Introduction to Windows Programming article 说
新应用程序应始终调用 Unicode 版本(API)。
TEXT 和 TCHAR 宏现在用处不大,因为所有应用程序都应该使用 Unicode。
我会坚持使用wchar_t
和L""
。
【讨论】:
史蒂文,您在引用一个不理解“Unicode”一词含义的人所写的文字。这是 UCS-2 混乱时期那些不幸的文件之一。 @PavelRadzivilovsky:该文档是为系统编写的,其中 Unicode 和 UTF-16LE 通常可以互换使用。虽然在技术上不准确,但它是明确的。这在同文的介绍中也明确指出:“Windows表示Unicode字符使用UTF-16编码[...]”.【参考方案8】:恕我直言,如果您的代码中有 TCHAR,则说明您在错误的抽象级别上工作。
在处理文本处理时,使用 whatever 字符串类型对您来说是最方便的 - 希望这将是支持 unicode 的东西,但这取决于您。根据需要在 OS API 边界进行转换。
处理文件路径时,请创建自己的自定义类型,而不是使用字符串。这将允许您独立于操作系统的路径分隔符,将为您提供比手动字符串连接和拆分更容易的编码接口,并且更容易适应不同的操作系统(ansi、ucs-2、utf-8 等) .
【讨论】:
Unicode 至少有三种当前编码(UTF-8、UTF-16、UTF-32)和一种不推荐使用的编码(UCS-2,现在 UTF-16 的子集)。你指的是哪一个?我喜欢其余的建议 +1【参考方案9】:我认为使用除显式 WCHAR 之外的任何内容的唯一原因是可移植性和效率。
如果您想让最终的可执行文件尽可能小,请使用 char。
如果您不关心 RAM 的使用并希望国际化像简单的翻译一样简单,请使用 WCHAR。
如果您想让您的代码灵活,请使用 TCHAR。
如果您只打算使用拉丁字符,您不妨使用 ASCII/MBCS 字符串,这样您的用户就不需要那么多 RAM。
对于“从一开始就是 i18n”的人,请节省源代码空间并简单地使用所有 Unicode 函数。
【讨论】:
【参考方案10】:我想建议一种不同的方法(两者都不是)。
总而言之,使用 char* 和 std::string,假设 UTF-8 编码,并且仅在包装 API 函数时才转换为 UTF-16。
有关在 Windows 程序中使用此方法的更多信息和理由,请访问 http://www.utf8everywhere.org。
【讨论】:
@PavelRadzivilovsky,在 VC++ 应用程序中实施您的建议时,我们会将 VC++ 字符集设置为“无”还是“多字节 (MBCS)”?我问的原因是我刚刚安装了 Boost::Locale 并且默认字符集是 MBCS。 FWIW,我的纯 ASCII 应用程序设置为“无”,现在我将其设置为“MBCS”(因为我将在其中使用 Boost::Locale),它工作得很好。请指教。 按照 utf8everywhere 的建议,我会将其设置为“使用 Unicode 字符集”。此广告额外安全,但不是必需的。 Boost::locale 的作者是一个非常聪明的人,不过我相信他做的没错。 UTF-8 Everywhere 咒语不会成为正确的解决方案,只是因为它被重复得更频繁。 UTF-8 无疑是一种有吸引力的序列化编码(例如文件或网络套接字),但在 Windows 上,使用本地 UTF-16 编码在内部存储字符数据并在应用程序边界进行转换通常更合适。一个原因是,UTF-16 是唯一可以立即转换为任何其他支持的编码的编码。 UTF-8 并非如此。 "..UTF-16 是唯一的编码,可以立即转换为任何其他支持的编码。"你的意思是?将 UTF-8 编码转换为其他编码有什么问题? 我不明白。对于其他任何事情——比如什么?例如。 UCS-4?为什么不?看起来很简单,全是数值算法..【参考方案11】:TCHAR
/WCHAR
对于一些遗留项目来说可能已经足够了。但对于新应用程序,我会说NO。
由于历史原因,所有这些TCHAR
/WCHAR
的东西都在那里。 TCHAR
提供了一种看似简洁的方式(伪装)在 ANSI 文本编码 (MBCS) 和 Unicode 文本编码 (UTF-16) 之间切换。过去,人们并不了解世界上所有语言的字符数。他们假设 2 个字节足以表示所有字符,因此具有使用 WCHAR
的固定长度字符编码方案。然而,在 1996 发布 Unicode 2.0 之后,情况就不再如此了。
也就是说:
无论您在CHAR
/WCHAR
/TCHAR
中使用哪个,您程序中的文本处理部分都应该能够处理变长字符以进行国际化。
所以你实际上需要做的不仅仅是从CHAR
/WCHAR
/TCHAR
中选择一个来在 Windows 中编程:
-
如果您的应用程序很小且不涉及文本处理(即仅将文本字符串作为参数传递),则坚持使用
WCHAR
。因为这种方式更容易使用支持 Unicode 的 WinAPI。
否则,我建议使用 UTF-8 作为内部编码并将文本存储在 char 字符串或 std::string 中。并在调用 WinAPI 时将它们转换为 UTF-16。 UTF-8 现在是主要的编码方式,有很多方便的库和工具可以处理 UTF-8 字符串。
查看这个精彩的网站以获得更深入的阅读: http://utf8everywhere.org/
【讨论】:
"UTF-8 现在是主要的编码" - 这变错了,因为省略了引号的第二部分 ("for the World Wide Web" )。对于桌面应用程序,最常用的本机字符编码可能仍然是 UTF-16。 Windows 使用它,Mac OS X 也使用它,.NET 和 Java 的字符串类型也是如此。这占了大量的代码量。不要误会我的意思,UTF-8 用于序列化没有任何问题。但通常情况下(尤其是在 Windows 上),您会发现在内部使用 UTF-16 更为合适。【参考方案12】:TCHAR
有了新的含义,将WCHAR
移植到CHAR
。
https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/use-utf8-code-page
Windows 10 的最新版本使用了 ANSI 代码页和 -A API 作为向应用程序引入 UTF-8 支持的一种方式。如果 ANSI 代码 页面配置为 UTF-8,-A API 以 UTF-8 运行。
【讨论】:
以上是关于TCHAR 仍然相关吗?的主要内容,如果未能解决你的问题,请参考以下文章
Django - MEDIA_URL 仍然与 S3BotoStorage 相关吗?
与现代 ORM 相比,MS SQL 上的 SELECT * 的性能/代码可维护性问题在今天仍然相关吗?
既然 Meteor 0.6.0+ 支持 npm 包,Meteorite 还相关吗?