我是Windows编程的新手,在阅读了Petzold的书之后,我想知道:
使用TCHAR
类型和_T()
函数来声明字符串或者我是否应该在新代码中使用wchar_t
和L""
字符串仍然是一种好习惯?
我将仅定位Windows 2000及以上版本,我的代码将从启动时开始i18n。
答案 0 :(得分:88)
答案简短:否。
与其他已经写过的人一样,很多程序员仍然使用TCHAR和相应的功能。在我的拙见中整个概念是一个坏主意。 UTF-16字符串处理与简单的ASCII / MBCS字符串处理有很大不同。如果你对它们使用相同的算法/函数(这就是TCHAR的想法所基于的!),如果你做的不仅仅是简单的字符串连接,你会在UTF-16版本上获得非常糟糕的性能(比如解析等)。主要原因是Surrogates。
唯一的例外是当您真的必须为不支持Unicode的系统编译您的应用程序时,我认为没有理由在新应用程序中使用过去的这个行李。
答案 1 :(得分:77)
我必须同意Sascha。 TCHAR
/ _T()
/等的基本前提是你可以编写一个基于“ANSI”的应用程序,然后通过定义宏来神奇地给它支持Unicode。但这是基于几个不好的假设:
您积极构建软件的MBCS和Unicode版本
否则,你将滑倒并在许多地方使用普通的char*
字符串。
在_T(“...”)文字中不使用非ASCII反斜杠转义
除非您的“ANSI”编码恰好是ISO-8859-1,否则生成的char*
和wchar_t*
文字将不代表相同的字符。
UTF-16字符串的使用方式与“ANSI”字符串相似
他们不是。 Unicode引入了大多数遗留字符编码中不存在的几个概念。代孕。结合人物。正常化。条件和语言敏感的套管规则。
也许最重要的是,UTF-16很少保存在磁盘上或通过互联网发送: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
。
忘记存在“ANSI”编码,除非您需要读取无效的UTF-8文件。忘掉TCHAR
。始终调用Windows API函数的“W”版本。 #define _UNICODE
只是为了确保您不会意外地调用“A”函数。
始终对字符串使用UTF编码:char
字符串的UTF-8和Windows上的UTF-16或wchar_t
字符串的UTF-32(在类Unix系统上)。 typedef
UTF16
和UTF32
个字符类型,以避免平台差异。
答案 2 :(得分:18)
如果你想知道它是否还在实践中,那么是 - 它仍然使用了很多。如果它使用TCHAR和_T(“”),没有人会看你的代码有趣。我正在研究的项目是从ANSI转换为unicode - 我们将采用便携式(TCHAR)路由。
<强> 然而... 强>
我的投票将是忘记所有ANSI / UNICODE可移植宏(TCHAR,_T(“”)和所有_tXXXXXX调用等...)并且只是假设unicode到处都是。如果你永远不需要ANSI版本,我真的没有看到便携的重点。我会直接使用所有宽字符函数和类型。使用L。预装所有字符串文字。
答案 3 :(得分:15)
如果我今天正在做一个新项目,我仍然会使用TCHAR语法。使用它和WCHAR语法之间没有太大的实际区别,我更喜欢在字符类型中明确的代码。由于大多数API函数和辅助对象采用/使用TCHAR类型(例如:CString),因此使用它是有意义的。此外,如果您决定在某个时刻使用ASCII应用程序中的代码,或者Windows曾经演变为Unicode32等,它会为您提供灵活性。
如果您决定采用WCHAR路线,我会明确表示。也就是说,使用CStringW而不是CString,并在转换为TCHAR时转换宏(例如:CW2CT)。
无论如何,这是我的意见。
答案 4 :(得分:11)
MSDN上的Introduction to Windows Programming article说
新应用程序应始终调用(API的)Unicode版本。
TEXT 和 TCHAR 宏今天不太有用,因为所有应用都应该使用Unicode。
我会坚持wchar_t
和L""
。
答案 5 :(得分:10)
我想建议一种不同的方法(两者都不是)。
总结一下,假设UTF-8编码使用char *和std :: string,并且只在包装API函数时才转换为UTF-16。
可以在http://www.utf8everywhere.org中找到有关Windows程序中此方法的更多信息和理由。
答案 6 :(得分:6)
TCHAR
/ WCHAR
可能就足够了。但对于新的应用程序,我会说 NO 。
由于历史原因,所有这些TCHAR
/ WCHAR
内容都在那里。 TCHAR
提供了一种在ANSI文本编码(MBCS)和Unicode文本编码(UTF-16)之间切换的简洁方式(伪装)。过去,人们并不了解世界上所有语言的字符数。他们假设2个字节足以表示所有字符,因此使用WCHAR
具有固定长度的字符编码方案。但是,在 1996 中发布Unicode 2.0后,情况就不再如此。
也就是说:
无论您在CHAR
/ WCHAR
/ TCHAR
中使用哪一个,程序中的文字处理部分都应该能够处理可变长度字符以进行国际化。< / p>
因此,您实际上需要做的不仅仅是从CHAR
/ WCHAR
/ TCHAR
中选择一个进行Windows编程:
WCHAR
。由于这种方式更容易使用支持Unicode的WinAPI。查看这个精彩的网站,以获得更深入的阅读: http://utf8everywhere.org/
答案 7 :(得分:4)
是的,绝对的;至少对于_T宏。不过,我对这个广泛的角色不太确定。
原因是更好地支持WinCE或其他非标准Windows平台。如果你100%确定你的代码将保留在NT上,那么你可以只使用常规的C字符串声明。但是,最好采用更灵活的方法,因为与通过数千行代码并在任何地方添加它以便在需要移植某些库时相比,在非Windows平台上#define该宏更容易到windows mobile。
答案 8 :(得分:2)
恕我直言,如果您的代码中存在TCHAR,那么您的抽象级别是错误的。
在处理文本处理时,使用任何字符串类型对您来说最方便 - 这有望支持unicode,但这取决于您。根据需要在OS API边界进行转换。
处理文件路径时,请使用自己的自定义类型而不是使用字符串。这将允许您独立于操作系统的路径分隔符,将为您提供比手动字符串连接和拆分更容易的代码接口,并且将更容易适应不同的操作系统(ansi,ucs-2,utf-8,等等)
答案 9 :(得分:2)
我看到使用除显式WCHAR之外的任何其他东西的唯一原因是可移植性和效率。
如果您想使最终的可执行文件尽可能小,请使用char。
如果您不关心RAM使用并希望国际化像简单翻译一样简单,请使用WCHAR。
如果您想使代码灵活,请使用TCHAR。
如果您只打算使用拉丁字符,那么您也可以使用ASCII / MBCS字符串,这样您的用户就不需要那么多的RAM。
对于那些“从一开始就是i18n”的人来说,请保存自己的源代码空间并简单地使用所有Unicode函数。
答案 10 :(得分:-1)
只是添加一个旧问题:
在VS2010中启动一个新的CLR C ++项目。微软自己使用L"Hello World"
,'nuff说。