c语言tchar头文件,c – 什么是TCHAR字符串和Win32 API函数的“A...

首先我要说的是,最好不要将TCHAR用于新的Windows项目,而应直接使用Unicode.关于实际答案:

字符集

我们需要了解的第一件事是字符集在Visual Studio中的工作原理.项目属性页面有一个选项可以选择使用的字符集:

>未设置

>使用Unicode字符集

>使用多字节字符集

根据您选择的三个选项中的哪一个,更改了许多定义以适应所选字符集.有三个主要类:字符串,来自tchar.h的字符串例程和API函数:

>’Not Set’对应于使用ANSI编码的TCHAR = char,其中您使用系统的标准8位代码页来表示字符串.所有tchar.h字符串例程都使用基本的char版本.所有使用字符串的API函数都将使用API??函数的“A”版本.

>’Unicode’对应于使用UTF-16编码的TCHAR = wchar_t.所有tchar.h字符串例程都使用wchar_t版本.所有使用字符串的API函数都将使用API??函数的“W”版本.

>’Multi-Byte’对应于TCHAR = char,使用一些多字节编码方案.所有tchar.h字符串例程都使用多字节字符集版本.所有使用字符串的API函数都将使用API??函数的“A”版本.

TCHAR.h标题

tchar.h头是一个帮助器,用于对字符串的C字符串操作使用通用名称,切换到给定字符集的正确函数.例如,_tcscat将切换到strcat(未设置),wcscat(unicode)或_mbscat(mbcs). _tcslen将切换到strlen(未设置),wcslen(unicode)或strlen(mbcs).

通过将所有_txxx符号定义为评估为正确函数的宏来进行切换,具体取决于编译器开关.

它背后的想法是你可以使用编码不可知的类型TCHAR(或_TCHAR)和与它们相关的编码不可知函数,来自tchar.h,而不是string.h中的常规字符串函数.

帮助宏_T(..)被定义为获取正确类型的字符串文字,“常规文字”或L“wchar_t文字”.

_tmain示例

对于问题中main的示例,以下代码将作为命令行参数传递的所有字符串连接成一个.

int _tmain(int argc, _TCHAR *argv[])

{

TCHAR szCommandLine[1024];

if (argc < 2) return 0;

_tcscpy(szCommandLine, argv[1]);

for (int i = 2; i < argc; ++i)

{

_tcscat(szCommandLine, _T(" "));

_tcscat(szCommandLine, argv[i]);

}

/* szCommandLine now contains the command line arguments */

return 0;

}

(省略了错误检查)此代码适用于字符集的所有三种情况,因为我们使用TCHAR,tchar.h字符串函数和字符串文字_T.在编写此类TCHAR程序时,忘记用_T(..)包围字符串文字是编译器错误的常见原因.

如果我们没有完成所有这些事情,那么切换字符集会导致代码无法编译,或者更糟糕的是,编译但在运行时期间行为异常.

Windows API函数

对字符串起作用的Windows API函数(如CreateFile和GetCurrentDirectory)在Windows标头中实现为宏,与tchar.h宏一样,切换到“A”版本或“W”版本.例如,CreateFile是一个宏,定义为ANSI和MBCS的CreateFileA,以及Unicode的CreateFileW.

无论何时在代码中使用平面形式(没有“A”或“W”),调用的实际函数将根据所选字符集进行切换.您可以使用显式的“A”或“W”名称强制使用特定版本.

结论是您应始终使用非限定名称,除非您希望始终引用特定版本,而与字符集选项无关.

对于问题中的示例,我们要打开第一个参数给出的文件:

int _tmain(int argc, _TCHAR *argv[])

{

if (argc < 2) return 1;

HANDLE hFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

/* Read from file and do other stuff */

...

CloseHandle(hFile);

return 0;

}

(省略错误检查)请注意,对于此示例,我们无需使用任何特定于TCHAR的东西,因为宏定义已经为我们处理了这个问题.

利用C字符串

我们已经看到了如何使用tchar.h例程来使用C样式的字符串操作来处理TCHAR,但如果我们可以利用C字符串来处理它,那将会很好.

我的建议最重要的是不使用TCHAR而是直接使用Unicode,请参阅结论部分,但如果您想使用TCHAR,则可以执行以下操作.

要使用TCHAR,我们想要的是使用TCHAR的std :: basic_string实例.您可以通过键入自己的tstring来完成此操作:

typedef std::basic_string tstring;

对于字符串文字,不要忘记使用_T.

您还需要使用正确版本的cin和cout.您可以使用引用来实现tcin和tcout:

#if defined(_UNICODE)

std::wistream &tcin = wcin;

std::wostream &tcout = wcout;

#else

std::istream &tcin = cin;

std::ostream &tcout = cout;

#end

这应该可以让你几乎做任何事情.可能偶尔会出现异常,例如std :: to_string和std :: to_wstring,您可以找到类似的解决方法.

结论

这个答案(希望如此)详细说明了TCHAR是什么以及它如何与Visual Studio和Windows标头一起使用和交织在一起.但是,我们也应该想知道是否要使用它.

我的建议是直接对所有新的Windows程序使用Unicode,而根本不使用TCHAR!

要在创建新项目后使用Unicode,请首先确保将字符集设置为Unicode.然后,删除#include< tchar.h>来自您的源文件(或来自stdafx.h).修复任何TCHAR或_TCHAR到wchar_t和_tmain到wmain:

int wmain(int argc, wchar_t *argv[])

对于非控制台项目,Windows应用程序的入口点是WinMain,并且将以TCHAR术语显示为

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

并且应该成为

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)

在此之后,只使用wchar_t字符串和/或std :: wstrings.

进一步的警告

>在使用TCHAR数组(字符串)时写入sizeof(szMyString)时要小心,因为对于ANSI,这是字符和字节的大小,对于Unicode,这只是字节大小,字符数最多为一半,对于MBCS,这是以字节为单位的大小,字符数可能相等也可能不相等. Unicode和MBCS都可以使用多个TCHAR来编码单个字符.

>混合TCHAR的东西和固定的char或wchar_t是非常烦人的;你必须使用正确的代码页将字符串从一个转换为另一个!简单副本在一般情况下不起作用.

>如果要有条件地定义自己的函数,_UNICODE和UNICODE之间会略有不同.见Why both UNICODE and _UNICODE?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值