size_t,__T,_T,TEXT,_TEXT等一些特殊宏的理解
Unicode解决方案
对于wchar_t在WCHAR.h中是这样定义的:
#define unsigned short wchar_t
那么现在你该理解它了吧。因此,wchar_t数据型态与无符号短整数型态相同,都是16位宽。
要定义包含一个宽字符的变量,可使用下面的语句:
wchar_t c = A ;
变量c是一个双字节值0x0041,是Unicode表示的字母A。(然而,因为Intel微处理器从最小的字节开始储存多字节数值,该字节实际上是以0x41、0x00的顺序保存在内存中。如果检查Unicode文字的计算机储存应注意这一点。)您还可定义指向宽字符串的指针:
wchar_t * p = L"Hello!" ;
注意紧接在第一个引号前面的大写字母L(代表「long」)。这将告诉编译器该字符串按宽字符保存-即每个字符占用2个字节。通常,指针变量p要占用4个字节,而字符串变量需要14个字节-每个字符需要2个字节,末尾的0还需要2个字节。同样,您还可以用下面的语句定义宽字符数组:
static wchar_t a[] = L"Hello!" ;
该字符串也需要14个字节的储存空间,sizeof (a) 将返回14。索引数组a可得到单独的字符。a[1] 的值是宽字符「e」,或者0x0065。虽然看上去更像一个印刷符号,但第一个引号前面的L非常重要,并且在两个符号之间必须没有空格。只有带有L,编译器才知道您需要将字符串存为每个字符2字 节。稍后,当我们看到使用宽字符串而不是变量定义时,您还会遇到第一个引号前面的L。幸运的是,如果忘记了包含L,C编译器通常会给提出警告或错误信息。
您还可在单个字符文字前面使用L前缀,来表示它们应解释为宽字符。如下所示:
wchar_t c = LA ;
但通常这是不必要的,C编译器会对该字符进行扩充,使它成为宽字符。宽字符链接库函数
我们都知道如何获得字符串的长度。例如,如果我们已经像下面这样定义了一个字符串指针:char * pc = "Hello!" ;
我们可以呼叫iLength = strlen (pc) ;
这时变量iLength将等于6,也就是字符串中的字符数。太好了!现在让我们试着定义一个指向宽字符的指针:
wchar_t * pw = L"Hello!" ;
再次呼叫strlen :iLength = strlen (pw) ;
现在麻烦来了。首先,C编译器会显示一条警告消息,可能是这样的内容:function : incompatible types - from unsigned short * to const char *
这条消息的意思是:声明strlen函数时,该函数应接收char类型的指标,但它现在却接收了一个unsigned short类型的指标。您仍然可编译并执行该程序,但您会发现iLength等于1。为什么?
字符串「Hello!」中的6个字符占用16位:
0x0048 0x0065 0x006C 0x006C 0x006F 0x0021
Intel处理器在内存中将其存为:48 00 65 00 6C 00 6C 00 6F 00 21 00
假定strlen函数正试图得到一个字符串的长度,并把第1个字节作为字符开始计数,但接着假定如果下一个字节是0,则表示字符串结束。这个小练习清楚地说明了C语言本身和执行时期链接库函数之间的区别。编译器将字符串L"Hello!" 解释为一组16位短整数型态数据,并将其保存在wchar_t数组中。编译器还处理数组索引和sizeof操作符,因此这些都能正常工作,但在连结时才添 加执行时期链接库函数,例如strlen。这些函数认为字符串由单字节字符组成。遇到宽字符串时,函数就不像我们所希望那样执行了。
您可能要说:「噢,太麻烦了!」现在每个C语言链接库函数都必须重写以接受宽字符。但事实上并不是每个C语言链接库函数都需要重写,只是那些有字符串参数的函数才需要重写,而且也不用由您来完成。它们已经重写完了。
strlen函数的宽字符版是wcslen(wide-character string length:宽字符串长度),并且在STRING.H(其中也说明了strlen)和WCHAR.H中均有说明。strlen函数说明如下:
size_t __cdecl strlen (const char *) ;
而wcslen函数则说明如下:size_t __cdecl wcslen (const wchar_t *) ;
这时我们知道,要得到宽字符串的长度可以呼叫iLength = wcslen (pw) ;
函数将返回字符串中的字符数6。请记住,改成宽字节后,字符串的字符长度不改变,只是位组长度改变了。您熟悉的所有带有字符串参数的C执行时期链接库函数都有宽字符版。例如,wprintf是printf的宽字符版。这些函数在WCHAR.H和含有标准函数说明的表头文件中说明。
维护单一原始码
当然,使用Unicode也有缺点。第一点也是最主要的一点是,程序中的每个字符串都将占用两倍的储存空间。此外,您将发现宽字符执行时期链接库中的函数 比常规的函数大。出于这个原因,您也许想建立两个版本的程序-一个处理ASCII字符串,另一个处理Unicode字符串。最好的解决办法是维护既能按 ASCII编译又能按Unicode编译的单一原始码文件。虽然只是一小段程序,但由于执行时期链接库函数有不同的名称,您也要定义不同的字符,这将在处理前面有L的字符串文字时遇到麻烦。
一个办法是使用Microsoft Visual C++包含的TCHAR.H表头文件。该表头文件不是ANSI C标准的一部分,因此那里定义的每个函数和宏定义的前面都有一条底线。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:
补充:综合编程 , 其他综合 ,