Unicode 字符串
2.8.1C运行期库对Unicode的支持
为了利用Unicode字符串,定义了一些数据类型。标准的C头文件String.h已经作了修改,以便定义一个名字为wchar_t的数据类型,它是一个Unicode字符的数据类型:例如,如果想要创建一个缓存,用于存放最多为99个字符的Unicode字符串和一个结尾为零的字符,可以使用下面这个语句:该语句创建了一个由100个16位值组成的数组。当然,标准的C运行期字符串函数,如strcpy、strchr和strcat等,只能对ANSI字符串进行操作,不能正确地处理Unicode字符串。因此,ANSIC也拥有一组补充函数。清单2-1显示了一些标准的ANSIC字符串函数,后面是它们的等价Unicode函数。清单2-1标准的ANSIC字符串函数和它们的等价Unicode函数请注意,所有的Unicode函数均以wcs开头,wcs是宽字符串的英文缩写。若要调用Unicode函数,只需用前缀wcs来取代ANSI字符串函数的前缀str即可。
注意大多数软件开发人员可能已经不记得这样一个非常重要的问题了,那就是Microsoft公司提供的C运行期库与ANSI的标准C运行期库是一致的。ANSIC规定,C运行期库支持Unicode字符和字符串。这意味着始终都可以调用C运行期函数,以便对Unicode字符和字符串进行操作,即使是在Windows98上运行,也可以调用这些函数。换句话说,wcscat、wcslen和wcstok等函数都能够在Windows98上很好地运行,这些都是必须关心的操作系统函数。
对于包含了对str函数或wcs函数进行显式调用的代码来说,无法非常容易地同时为ANSI和Unicode对这些代码进行编译。本章前面说过,可以创建同时为ANSI和Unicode进行编译的单个源代码文件。若要建立双重功能,必须包含TChar.h文件,而不是包含String.h文件。
TChar.h文件的唯一作用是帮助创建ANSI/Unicode通用源代码文件。它包含你应该用在源代码中的一组宏,而不应该直接调用str函数或者wcs函数。如果在编译源代码文件时定义了UNICODE,这些宏就会引用wcs这组函数。如果没有定义_UNICODE,那么这些宏将引用str这组宏。
例如,在TChar.h中有一个宏称为_tcscpy。如果在包含该头文件时没有定义_UNICODE,那么_tcscpy就会扩展为ANSI的strcpy函数。但是如果定义了_UNICODE,_tcscpy将扩展为Unicode的wcscpy函数。拥有字符串参数的所有C运行期函数都在TChar.h文件中定义了一个通用宏。如果使用通用宏,而不是ANSI/Unicode的特定函数名,就能够顺利地创建可以为ANSI或Unicode进行编译的源代码。
但是,除了使用这些宏之外,还有一些操作是必须进行的。TChar.h文件包含了另外一些宏.若要定义一个ANSI/Unicode通用的字符串数组,请使用下面的TCHAR数据类型。如果定义了_UNICODE,TCHAR将声明为下面的形式:如果没有定义_UNICODE,则TCHAR将声明为下面的形式:使用该数据类型,可以像下面这样分配一个字符串:也可以创建对字符串的指针:不过上面这行代码存在一个问题。按照默认设置,Microsoft公司的C++编译器能够编译所有的字符串,就像它们是ANSI字符串,而不是Unicode字符串。因此,如果没有定义_UNICODE,该编译器将能正确地编译这一行代码。但是,如果定义了_UNICODE,就会产生一个错误。若要生成一个Unicode字符串而不是ANSI字符串,必须将该代码行改写为下面的样子:字符串(literalstring)前面的大写字母L,用于告诉编译器该字符串应该作为Unicode字符串来编译。当编译器将字符串置于程序的数据部分中时,它在每个字符之间分散插入零字节。这种变更带来的问题是,现在只有当定义了_UNICODE时,程序才能成功地进行编译。我们需要另一个宏,以便有选择地在字符串的前面加上大写字母L。这项工作由_TEXT宏来完成,_TEXT宏也在TChar.h文件中做了定义。如果定义了_UNICODE,那么_TEXT定义为下面的形式:如果没有定义_UNICODE,_TEXT将定义为使用该宏,可以改写上面这行代码,这样,无论是否定义了_UNICODE宏,它都能够正确地进行编译。如下所示:_TEXT宏也可以用于字符串。例如,若要检查一个字符串的第一个字符是否是大写字母J,只需编写下面的代码即可:2.8.2Windows定义的Unicode数据类型
Windows头文件定义了表2-3列出的数据类型。
表2-3Uincode数据类型
数据类型
说明
WCHAR
Unicode字符
PWSTR
指向Unicode字符串的指针
PCWSTR
指向一个恒定的Unicode字符串的指针
这些数据类型是指Unicode字符和字符串。Windows头文件也定义了ANSI/Unicode通用数据类型PTSTR和PCTSTR。这些数据类型既可以指ANSI字符串,也可以指Unicode字符串,这取决于当编译程序模块时是否定义了UNICODE宏。
请注意,这里的UNICODE宏没有前置的下划线。_UNICODE宏用于C运行期头文件,而UNICODE宏则用于Windows头文件。当编译源代码模块时,通常必须同时定义这两个宏。
2.9成为符合ANSI和Unicode的应用程序
即使你不打算立即使用Unicode,最好也应该着手将你的应用程序转换成符合Unicode的应用程序。下面是应该遵循的一些基本原则: