编码的发展历史:
1.ASCII
美国信息交换标准码(ASCII:American Standard Code for Information Interchange)起始于50年代后期,最后完成于1967年。综合考虑不采用字符替换以及成本问题,采用7位,
2.扩展ASCII
因为遵循了ANSI草案和ISO标准,纯Windows字符集被称作「ANSI字符集」。ANSI草案和ISO标准最终成为ANSI/ISO 8859-1-1987,即「American National Standard for Information Processing-8-Bit Single-Byte Coded Graphic Character Sets-Part 1: Latin Alphabet No 1」,通常也简写为「Latin 1」。其中采用了8位进行存储,增加了一些西欧语言的字符及符号。空方框表示该位置未定义字符。
3.双字节字符集
中国、日本和韩国的象形文字符号有大约21,000个。为了容纳这些语言,早期采用了双字节字符集(DBCS:double-byte character set)。
DBCS从256代码开始,就像ASCII一样。与任何行为良好的代码页一样,最初的128个代码是ASCII。然而,较高的128个代码中的某些总是跟随着第二个字节。这两个字节一起(称作首字节和跟随字节)定义一个字符,通常是一个复杂的象形文字。
虽然中文、日文和韩文共享一些相同的象形文字,但显然这三种语言是不同的,而且经常是同一个象形文字在三种不同的语言中代表三件不同的事。Windows支持四个不同的双字节字符集:代码页932(日文)、936(简体中文)、949(韩语)和950(繁体汉字)。只有为这些国家(地区)生产的Windows版本才支持DBCS。
双字符集问题并不是说字符由两个字节代表。问题在于一些字符(特别是ASCII字符)由1个字节表示。这会引起附加的程序设计问题。例如,字符串中的字符数不能由字符串的字节数决定。必须剖析字符串来决定其长度,而且必须检查每个字节以确定它是否为双字节字符的首字节。如果有一个指向DBCS字符串中间的指针,那么该字符串前一个字符的地址是什么呢?惯用的解决方案是从开始的指针分析该字符串!
4.Unicode
Unicode是统一的16位系统,这样就允许表示65,536个字符。
处理DBCS字符串非常杂乱,但是处理Unicode文字则像处理有秩序的文字。您也许会高兴地知道前128个Unicode字符(16位代码从0x0000到0x007F)就是ASCII字符,而接下来的128个Unicode字符(代码从0x0080到0x00FF)是ISO 8859-1对ASCII的扩展。Unicode中不同部分的字符都同样基于现有的标准。这是为了便于转换。希腊字母表使用从0x0370到0x03FF的代码,斯拉夫语使用从0x0400到0x04FF的代码,美国使用从0x0530到0x058F的代码,希伯来语使用从0x0590到0x05FF的代码。中国、日本和韩国的象形文字(总称为CJK)占用了从0x3000到0x9FFF的代码。
字符在C中的处理:
普通的char变量为1字节存储,char*为4字节。
C中的宽字符基于wchar_t数据型态,它在几个表头文件包括WCHAR.H中都有定义,像这样:
- typedef 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。
strlen等的问题:
strlen遇到0识别字符串结束,而unicode中的字母一般为00XX保存,在intel处理器中小端存储为XX 00,则会直接识别为字符串结束。
所以对应采用wcslen
为了兼容这两种字符编码,就出现了tchar.h
_tcslen
TCHAR
__T(x) _T(x) _TEXT(x)
windows.h及其所包含的的头文件中(WINNT.H):
- typedef char CHAR ;
- typedef wchar_t WCHAR ; // wc
- typedef CHAR * PCHAR, * LPCH, * PCH, * NPSTR, * LPSTR, * PSTR ;
- typedef CONST CHAR * LPCCH, * PCCH, * LPCSTR, * PCSTR ;
- typedef WCHAR * PWCHAR, * LPWCH, * PWCH, * NWPSTR, * LPWSTR, * PWSTR ;
- typedef CONST WCHAR * LPCWCH, * PCWCH, * LPCWSTR, * PCWSTR ;
WINNT.H将TCHAR定义为一般的字符类型。如果定义了标识符UNICODE(没有底线),则TCHAR和指向TCHAR的指标就分别定义为WCHAR和指向WCHAR的指标;如果没有定义标识符UNICODE,则TCHAR和指向TCHAR的指标就分别定义为char和指向char的指标:
- #ifdef UNICODE
- typedef WCHAR TCHAR, * PTCHAR ;
- typedef LPWSTR LPTCH, PTCH, PTSTR, LPTSTR ;
- typedef LPCWSTR LPCTSTR ;
- #else
- typedef char TCHAR, * PTCHAR ;
- typedef LPSTR LPTCH, PTCH, PTSTR, LPTSTR ;
- typedef LPCSTR LPCTSTR ;
- #endif