分享
 
 
 

《Windows程序设计》读书笔记之二

王朝system·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

Unicode简介

见钱眼开 于2005-3-1

为什么需要Unicode编码?因为ASCII编码无法表示足够多的字符。在ASCII编码中,每个字符用7位表示,可以表示128个不同字符;在Unicode中,每个字符用16位表示,可以表示216即65536个不同字符。

为什么双字节字符集(DBCS:double-byte character set)不能完全满足需要?在双字节字符集中,最初的128个编码(0-127)就是ASCII,从128(0x80)开始,由两个字节组成一个字符。这就带来了附加的编程问题。难以凭字节数决定字符数,难以进行字符串指针操作。而Unicode所有字符都是两字节的,不会带来编程中的问题,唯一不足就是会占用更多的磁盘空间。

在C程序中,使用char类型以1字节长度定义存储1个字符,如:

char c = ‘A’; //变量c大小为1字节,存储内容为0x41

对于Unicode字符,采用wchar_t类型以2个字节长度定义存储1个字符。如:

wchar_t d = L’A’; //变量d大小为2字节,存储内容为0x0041

其实wchar_t和无符号短整型等价,都是16位宽:

typedef unsigned short wchar_t;

至于字符串前的大写字母L,是个修饰符号,告诉编译器要为该字符串每个字符分配2字节内存。

对于宽字符,ANSI C标准提供了新的字符处理库函数,这些函数在string.h和wchar.h中都有声明。例如原strlen函数,对应的宽字符版本函数原型声明如下:

size_t __cdecl wcslen(const wchar_t* );

但这样带来的问题是如何在一个程序中同时可以处理两种字符类型呢?

一个办法是使用Visual C++包含的tchar.h头文件,该头文件不是ANSI C标准一部分,所以每个定义的函数和宏定义前都一个条下划线。如果定义了_UNICODE标识符,进行下列宏定义:

#define _tcslen wcslen

否则定义:

#define _tcslen strlen

在tchar.h头文件中还增加了一种TCHAR类型来解决两种字符类型的问题。如果定义了_UNICODE标识符,进行下列类型等价声明:

typedef wchar_t TCHAR;

#define __T(x) L##x 或者 #define _T(x) L##x 或者 #define _TEXT(x) L##x

否则声明:

typedef char TCHAR;

#define __T(x) x 或者 #define _T (x) x 或者 #define _TEXT(x) x

以上这些都是基于C运行时库的声明定义,在Windows下Microsoft重新定义了新的数据类型和函数,可以在winnt.h头文件中我们可以看到:

typedef char CHAR

typedef wchar_t WCHAR

typedef CHAR *PCHAR,*LPCH,*PCH,*NPSTR,*LPSTR,*PSTR;

typedef CONST CHAR *LPCCH,*PCCH,*LPCSTR,*PCSTR;

typedef WCHAR *PWCHAR,*LPWCH,*PWCH,*NPWSTR,*LPWSTR,*PWSTR;

typedef CONST WCHAR *LPCWCH,*PCWCH,*LPCWSTR,*PCWSTR;

如果定义了UNICODE标识符(没有下划线),则将TCHAR和指向TCHAR指针定义为WCHAR和指向WCHAR指针,否则定义为CHAR和指向CHAR指针。此外,在Winnt头文件中还增加了一个宏,就是将L添加到字符串的第一个引号前。

#ifdef UNICODE

#define __TEXT(quote) L##quote

#else

#define __TEXT(quote) quote

#endif

windows NT完全支持Unicode。因此大多数API函数都存在两种版本声明定义,通常根据UNICODE标识符来定位不同函数入口点。

C运行时库函数已经提供完善的字符处理功能,但为了更方便windows下程序开发的需要,Windows中重新定义了一些类似的字符处理函数。

遗憾的是,printf在windows程序中已经不能使用。我们仍可以使用sprintf和vsprintf。printf函数声明如下:

int printf(const char* pszFormat,…);

首个参数是格式字符串,后面是对应格式字符串的若干个参数

int sprintf(char* pszBuffer,const char* pszFormat,…);

首个参数是字符缓冲区,其他参数和printf函数参数含义一致。Sprintf函数将结果写入字符缓冲区

int __cdecl vsprintf(char * pszBuffer, const char * pszFormat, va_list ArgsList);

首个参数是字符缓冲区,第二个参数是格式字符串,最后一个参数是指向格式化参数数组的指针,实际上该指针指向在堆栈中供函数调用的变量。

Vsprintf函数使用实例如下:

int __cdecl ShowMessage(char* pzsCaption,char* pszFormat,…)

{

char* pszBuffer[256];

va_list pArgList;

va_start(pArgList,pszFormat);

vsprintf(pszBuffer,pszFormat,pArgList);

va_end(pArgList);

return MesageBox(NULL,pszBuffer,szCaption,0);

}

使用sprintf和vsprintf函数的问题是无法保证字符缓冲区不溢出。

_snprintf函数通过增加一个缓冲区可容纳字符数大小参数解决了以上问题。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有