您的位置:首页 > 编程语言 > C语言/C++

Windows Via C/C++ Part Ⅰ Chapter 2: 字符和字符串(1)

2009-08-15 00:02 495 查看
[有删改]

(一) 字符编码

  如何处理不同的字符集一直是应用程序本地化的难题。一直以来,大多数开发人员将字符串编码为以0结尾的单字节字符序列,这是很自然的,当我们调用strlen时,它会返回以0结尾的字符数组中的字符数目——以单字节的形式。  

  然而有些语言的符号(如日本语),无法用只包含256个字符的单字节字符集完整描述。因此出现了双字节字符集(Double-Byte Character Sets-DBCSs)来支持这些语言。在DBCSs中,每个字符用1个或2个字节构成。以日本语为例,如果某字节在0x81~0x9F之间或0xE0~0XFC之间,则该字节是某个字符的首字节,我们必须查看下一个字节以确定完整的字符。由于DBCSs中的字符宽度不是固定的,对开发人员而言这简直是一场噩梦。幸运的是,现在我们可以用Windows函数和C运行时库函数支持的unicode字符串来避免这些问题。

  Unicode标准由Apple和Xerox在1988年共同制定。1991年,Apple、Compaq、IBM、Microsoft等成立了Unicode协会以维持和发展Unicode标准。完整的Unicode标准描述可以参阅 Addison-Wesley出版社出版的《The Unicode Standard》一书(可以通过 http://www.Unicode.org 获得该书)。

  Windows Vista使用UTF-16编码,UTF是Unicode Transformation Format的缩写。UTF-16中的每个字符用两个字节编码。[此处有一段说明UTF-16格式好处的原因,省略]。除了UTF-16,Unicode还包括两种编码标准:

UTF-8: UTF-8中每个字符用1、2、3或4个字节表示,这比DBCSs更让人崩溃。

UTF-32: UTF-32将每个字符用4个字节编码。显然这并不是一个非常高效的选择。

  目前,Unicode已为阿拉伯语、汉语、斯拉夫语、德语、希伯来语、日文、棒子语以及拉丁(英文)等字符系统定义了代码点。每个新版本的Unicode为已存在于Unicode标准中的字符系统引入新的字符甚至是全新的字符系统(如Phoenician -腓尼基语)。在Unicode定义的字符系统中,包括了大量的标点符号、数学符号、工业符号、箭头符号、图像符号、音标符号和其它常用字符。UTF-32标准中的65 536个字符按照区域可做如下划分:     
16-Bit Code

Characters
16-Bit Code
Alphabet/Scripts
0000-007F
ASCII
0300-036F
Generic diacritical marks
0080-00FF
Latin1 characters
0400-04FF
Cyrillic
0100-017F
European Latin
0530-058F
Armenian
0180-01FF
Extended Latin
0590-05FF
Hebrew
0250-02AF
Standard phonetic
0600-06FF
Arabic
02B0-02FF
Modified letters
0900-097F
Devanagari
(二) ANSI/UNICODE字符(串)数据类型

  C语言使用char数据类型表示8位的ANSI字符。当你在代码中声明字符串常时,C编译器会把字符串转换为8位的char类型序列:

  
]/* 8位的char字符 */
char c = 'a';

/* 8位的char数组,包含0结束符*/
char szBuffer[100] = "a string";


  微软的C/C++编译器定义了一种内置数据类型:wchar_t,注意这并不是定义在 wchar.h头文件中的wchar_t(unsigned short),而是内置的。wchar_t代表16位的Unicode字符。由于早期的微软编译器并没有提供这种内置类型,因此在使用早期编译器时必须手工指定/Zc:wchar_t编译选项。当你使用Visual Studio创建新的C++项目时,/Zc:wchar_t是默认打开的。一直打开/Zc:wchar_t是一种好习惯,因为内置的原始数据类型更容易被编译器所理解。Unicode字符和字符串可按如下方式声明:

  
/* 16位的unicode字符 */
wchar_t c = L'a';

/* unicode字符串,以0结尾 */
wchar_t szBuffer[] = L"a unicode string";
   

  字符串前面的L前缀告诉编译器被它修饰的字符串应该按照Unicode编码对待。当编译器将字符串放到程序的数据段时,它把字符串的每个字符编码为UTF16格式,如果其中含有ASCII字符,则在其高位补0。微软的Windows小组定义了一些和C语言稍有区别的数据类型,在WinNT.h中,可以看到如下定义:

  
typedef char     CHAR;
typedef wchar_t  WCHAR;


   此外,WinNT.h中定义了一些常用的指向字符和字符串的指针类型,如:

  
/* Pointer to 8-bit character(s) */
typedef CHAR  *PCHAR;
typedef CHAR  *PSTR;
typedef CONST  CHAR  *PCSTR;

/* Pointers to 16-bit character(s) */
typedef WCHAR  *PWCHAR;
typedef WCHAR  *PWSTR;
typedef CONST WCHAR  *PCWSTR;
  

  注意:在WinNT.h中,你可能会发现如下定义:

  typedef __nullterminated WCHAR *NWPSTR, *LPWSTR, *PWSTR;

  标识符用来指示函数的参数或返回值的期望类型,这只在Visual Studio 企业版中有效,向编译选项中添加/analyze可以打开该功能。

  在你自己的代码中,使用何种数据类型并不重要,但我依然建议你为提高代码的可维护性使用Windows数据类型,和MSDN文档的用法一致,这样会让代码更为清晰。同时兼容ANSI和Unicode编码的代码是可以实现的,在WinNT.h中定义了下面的宏:

  
#ifdef UNICODE

typedef WCHAR TCHAR, *PTCHAR, *PTSTR
typedef CONST WCHAR  *PCTSTR;
#define __TEXT(quote) L##quote

#else

typedef CHAR TCHAR, *PTCHAR, *PTSTR
typedef CONST CHAR *PCTSTR;
#define __TEXT(quote) quote

#endif

#define TEXT(quote) __TEXT(quote)


  这些宏可以帮助我们编写兼容ANSI和Unicode的代码,如:

  
]/* 如果定义了UNICODE,则c为16位,否则为8位 */
TCHAR c = TEXT('A');

/* 如果定义了UNICODE,则szBuffer为16位字符数组,否则为8位 */
TCHAR szBuffer[] = TEXT("a string");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: