简单来说,unicode用的是16位字符编码,而不是像ASCII那样7位代表一个字符,也不是计算机上常见的每个字符8位的方式。
一、宽字符和c语言
ASCII中字符类型举例:
char c='A'; char * p="Hello"; char a[]="Hello";
Unicode中字符定义:
c语言中宽字符是基于wchar_t数据类型的(定义在多个头文件,包括WCHAR.H:typedef unsigned short wchar_t)。
wchar_t c='A'; wchar_t *p=L“Hello”;(指针仍然4个字节,L要紧靠字符串,表明用宽字符存储,每个字符两个字节)。
二、宽字符库函数
我们不需要重写库函数,因为重写已经完成。
宽字符版本的strlen函数被称为wcslen(宽字符字符串函数)并定义在STRING.H(也就是strlen被定义的地方)和WCHAR.H中
strlen函数声明如下: size_t _cdecl strlen(const char*);
而wcslen函数的声明如下: size_t _cdecl wcslen(const wchar_t*);
char * p="Hello";
iLength=wcslen(p); 结果仍然是6,也就是字符串中字符的个数。
请记住:在使用宽字符的时候,字符串的长度并没有改变,改变的只是字节数。
三、维护一个源代码文件
当我们编写一个程序时,是否要编写两个版本呢,一个ASCII版本,一个是Unicode版本?
答案是不需要。
一个答案是使用VC++中的TCHAR.H头文件。这个头文件并不是ASCII中的一部分,所以其中定义的每一个函数和宏都有一个下划线前缀。TCHAR.H为那些需要字符串参数的普通运行库函数(例如,_tprintf 和 _tcslen)提供了一系列的替代名。这些函数有时被称为“通用”的函数名字,因为他们可以指Unicode或非Unicode版本的函数。
如果一个命名为_UNICODE的标示符被定义了并且TCHAR.H头文件被包含在你的程序中,_tcslen就被定义为wcslen: #define _tcslen wcslen
如果UNICODE并没有被定义,那么_tcslen就被定义为strlen: #define _tcslen strlen
以此类推,TCHAR.H也用一个命名为TCHAR的新的数据类型解决了两个数据类型的问题。如果UNICODE标识符被定义了,TCHAR就是wchar_t: typedef wchar_t TCHAR
否则的话,TCHAR就是一个简单的char: typedef char TCHAR 。
现在解决字符串文本中L这一棘手问题了!
如果UNICODE标识符被定义,一个叫_T 的宏是如下定义的: #define _T(x) L##x
这是相当模糊的说法,但它在ANSI标准c预处理器中,那一对数字符号被称为“令牌黏贴”,它使得L和宏参数拼接在一起,因此,如果宏参数是“Hello”,那么L##x就是L"Hello"!
如果UNICODE标识符没有被定义,_T宏就如下定义:
#define _T(x) x
无论如何,其他两个宏是定义成和_T一样的:
#define _T(x) _T(x)
#define _TEXT(x) _T(x)
Win32控制台程序使用哪一种取决于你所需要的简明或详细程度。基本上,必须用下列方法将字符串字面定义在_T或_TEXT宏内:
_TEXT("Hello");
这样做的结果是,如果UNICODE标识符被定义了,字符串就被解释为有宽字符组成的,否则,它被解释成8位的字符串。