Unicode学习

来源:互联网 发布:淘宝如何增加客服 编辑:程序博客网 时间:2024/05/16 10:52

1.主要的字符编码
(1)美国信息交换标准码ASCII,每个字符用7位表示,总共128个字符码,无法良好满足其他国家的需要。
(2)扩展ASCII,如使用代码页,代码页定义了字符的映像代码,编码比较混乱。
(3)双字节字符集DBCS,可以处理8位或16位的数值。有些字节自身定义字符,而某些字节则显示需要和另一个字节共同定义一个字符,这会引起附加的程序设计问题。
(4)Unicode,每个字符都是16位宽。其缺点是占用内存是ASCII字符串的两倍。

 


2.宽字符和Unicode
宽字符是C中的概念,表示用多个字节代表一个字符的字符集。
宽字符不需要是Unicode,Unicode只是一种可能的宽字符集。但Windows下的宽字符一般就是指Unicode。

 


3.宽字符和C
(1)C中的宽字符基于wchar_t类型,定义如下:
typedef unsigned short wchar_t ;
定义包含一个宽字符的变量:
wchar_t c = 'A' ;
定义指向宽字符串的指针:
wchar_t * p = L"Hello!" ;
注:L(代表「long」),这将告诉编译器该字符串按宽字符保存,即每个字符占用2个字节。通常,指针变量p要占用4个字节,而字符串变量需要14个字节,每个字符需要2个字节,末尾的0还需要2个字节。而上面定义单个字符通常不需要加L。


(2)所有带有字符串参数的C执行时期链接库函数都有宽字符版,如strlen对应宽字符版wcslen,printf对应宽字符版wprintf。
为了维护单一原始码,可以使用TCHAR.H头文件。因为该文件不是ASNI C标准的一部分,所以它定义的每个函数和宏定义前都有下划线。
TCHAR.H为需要字符串参数的标准执行时期链接库函数提供了一系列的替代名称(例如,_tprintf和_tcslen)。有时这些名称也称为「通用」函数名称,因为它们既可以指向函数的Unicode版也可以指向非Unicode版。最终使用哪个版本取决于是否定义了名为_UNICODE的标识符。
TCHAR.H还用一个新的数据类型TCHAR来解决两种字符数据类型的问题。TCHAR为char还是wchar_t,也取决于是否定义了名为_UNICODE的标识符。
为了解决字符串文字中的L问题,TCHAR.H还定义了_T的宏。如果定义了_UNICODE标识符,定义为#define __T(x) L##x,其中一对井号为粘贴符号,否则定义为#define __T(x) x 。另外还有两个宏与__T定义相同:
#define _T(x)__T(x)       
#define _TEXT(x)__T(x)  

 


4.宽字符和Windows
Windows NT从底层支援Unicode,这意味着Windows NT内部使用由16位字符组成的字符串。这也表明使用Unicode开发程序更高效。Windows 98部分支持Unicode。
(1)Windows中WINNT.H定义了新的数据类型CHAR和WCHAR,定义如下:
typedef char CHAR ;       
typedef wchar_t WCHAR ;    // wc    
WINNT.H也定义了TCHAR类型为一般的字符类型,TCHAR指CHAR还是WCHAR,取决于是否定义了名为UNICODE的标识符。注意是没有下划线的UNICODE,与C运行期头文件_UNICODE 区别。
同样的WINNT.H也定义了_TEXT宏,如果定义了UNICODE标识符,则:
#define __TEXT(quote) L##quote   
否则:
#define __TEXT(quote) quote   
同样还有:
#define TEXT(quote) __TEXT(quote)    
即不用操心下划线的问题了。
(2)Windows函数调用
同C函数一样也有两个版本。如MessageBox函数,有两个进入点,一个名为MessageBoxA(ASCII版),另一个名为MessageBoxW(宽字符版)。具体调用哪个取决于是否定义了UNICODE标识符。

 


小结:
这些定义可使您在同一程序中混合使用ASCII和Unicode字符串,或者编写一个可被ASCII或Unicode编译的程序。如果您希望明确定义8位字符变量和字符串,请使用CHAR、PCHAR(或者其它),以及带引号的字符串。为明确地使用16位字符变量和字符串,请使用WCHAR、PWCHAR,并将L添加到引号前面。对于是8位还是16位取决于UNICODE标识符的定义的变量或字符串,要使用TCHAR、PTCHAR和TEXT宏。

 


说明:
(1)自Windows NT 起,Windows的所有版本都完全用Unicode来构建。调用Windows函数时,如果传入一个ANSI字符串(有单字节字符组成的一个字符串),那么操作系统会先把字符串转换为Unicode,再把结果传给操作系统。如果希望函数返回ANSI字符串,那么操作系统会先把Unicode字符转换为ANSI字符串,再把结果返回给我们的应用程序。所有这些转换都是在幕后进行的。当然,这样系统会产生时间和内存上的开销。
C运行库与Windows不同,它也提供了ANSI版和Unicode版的函数,但它们都是“自力更生”的,即调用ANSI版本的函数,它们不会将字符串转换为Unicode形式;调用Unicode版本的函数,它们也不会将字符串转换为ANSI形式。


(2)应用程序中,应确保要么同时定义了UNICODE和_UNICODE,要么一个都不要定义。
定义的方法可以使用宏定义语句:
#ifndef UNICODE
 #define UNICODE
#endif

 

#ifdef UNICODE
 #ifndef _UNOCODE
  #define _UNICODE
 #endif
#endif
也可以采用另一种办法:
在VC++菜单中设置:Project->Settings->C/C++->Preprocessor definitions中添加UNICODE和_UNICODE的定义。


(3)推荐的字符和字符串处理方式
用通用数据类型(如TCHAR/PTSTR)来表示文本字符和字符串。
用TEXT或_T宏来表示字面量字符和字符串。

 

 

参考文献:
《Windows程序设计》,《Windows核心编程》

原创粉丝点击