为简化代码传输以方便国际使用,Microsoft 运行时库为许多数据类型、例程和其他对象提供 Microsoft 特定的“一般文本”映射。您可以使用 Tchar.h 中定义的这些映射,根据使用 #define 语句定义的清单常数,编写可以为单字节、多字节或 Unicode 编译的一般代码。一般文本映射是与 ANSI 不兼容的 Microsoft 扩展。
使用 Tchar.h 可以从同一个源中生成单字节、MBCS 和 Unicode 应用程序。Tchar.h 定义以 _tcs 为前缀的宏,这些宏根据正确的预处理器定义映射到适当的 str、_mbs 或 wcs 函数。若要生成 MBCS,请定义 _MBCS 符号。若要生成 Unicode,请定义 _UNICODE 符号。若要生成单字节应用程序,请不进行任何定义(默认)。默认情况下,为 MFC 应用程序定义的是 _MBCS。
在 Tchar.h 中根据条件定义 _TCHAR 数据类型。如果为您的版本定义了 _UNICODE 符号,则 _TCHAR 被定义为 wchar_t;否则,对于单字节和 MBCS 版本,_TCHAR 被定义为 char。((wchar_t 是基本的 Unicode 宽字符数据类型,它是 8 位有符号 char 的 16 位对等项。)对于国际应用程序,使用以 _TCHAR(而非字节)为单位进行操作的 _tcs 函数族。例如,_tcsncpy 复制 n 个 _TCHAR,而不是 n 个字节。
由于某些 SBCS 字符串处理函数采用(有符号的)char* 参数,因此定义 _MBCS 时将产生类型不匹配的编译器警告。有三种方法避免此警告,按效率高低的顺序依次为:
-
在 Tchar.h 中使用类型安全内联函数 thunk。这是默认行为。
-
通过在命令行上定义 _MB_MAP_DIRECT,在 Tchar.h 中使用直接宏。如果这样做,必须手动匹配类型。这是最快的方法,但不是类型安全的方法。
-
在 Tchar.h 中使用“类型安全”静态链接库函数 thunk。若要这样做,请在命令行上定义 _NO_INLINING 常数。这是最慢的方法,但却是类型安全性最高的方法。
一般文本映射的预处理器指令
#define | 编译版本 | 示例 |
_UNICODE | Unicode(宽字符) | _tcsrev 映射到 _wcsrev |
_MBCS | 多字节字符 | _tcsrev 映射到 _mbsrev |
无(默认:既未定义 _UNICODE 也未定义 _MBCS) | SBCS (ASCII) | _tcsrev 映射到 strrev |
例如,如果在程序中定义了 _MBCS,则 Tchar.h 中定义的一般文本函数 _tcsrev 映射到 _mbsrev。或者如果在程序中定义了 _UNICODE,则 _tcsrev 映射到 _wcsrev。否则 _tcsrev 映射到 strrev。在 Tchar.h 中还提供了其他数据类型映射以方便编程,但 _TCHAR 是最有用的。
一般文本数据类型映射
一般文本数据类型名称 | _UNICODE 和 _MBCS 未定义 | _MBCS 已定义 | _UNICODE 已定义 |
_TCHAR | char | char | wchar_t |
_TINT | int | int | wint_t |
_TSCHAR | signed char | signed char | wchar_t |
_TUCHAR | unsigned char | unsigned char | wchar_t |
_TXCHAR | char | unsigned char | wchar_t |
_T 或 _TEXT | 无效(由预处理器移除) | 无效(由预处理器移除) | L(将后面的字符或字符串转换成相应的 Unicode 形式) |
有关例程、变量和其他对象的一般文本映射的完整列表,请参见“运行时库参考”中的一般文本映射。
注意
Unicode 字符串有可能包含嵌入空字节,所以不要在 Unicode 字符串中使用 str 函数族。同样道理,不要在 MBCS(或 SBCS)字符串中使用 wcs 函数族。
下列代码片段阐释了有关映射到 MBCS、Unicode 和 SBCS 模型的 _TCHAR 和 _tcsrev 的用法。
- _TCHAR *RetVal, *szString;
- RetVal = _tcsrev(szString);
如果已定义 _MBCS,则预处理器将此片段映射到下列代码:
char *RetVal, *szString; RetVal = _mbsrev(szString);
如果已定义 _UNICODE,则预处理器将此片段映射到下列代码:
wchar_t *RetVal, *szString; RetVal = _wcsrev(szString);
如果既未定义 _MBCS 也未定义 _UNICODE,则预处理器将此片段映射到单字节 ASCII 代码:
char *RetVal, *szString; RetVal = strrev(szString);
因此可以编写、维护和编译与三种字符集中任何一种的特定例程一起运行的单个源代码文件。