ASCII、ANSI、MBCS、UNICODE字符集

1. 三种计算机字符集

计算机字符集可归类为三种,单字节字符集(SBCS)、多字节字符集(MBCS)和宽字符集(即Unicode字符集)。

单字节字符集(SBCS):

单字节字符集,称之为SBCS,它的所有字符都只有一个字节的长度。常见字符集有:ASCII码和扩展ASCII码。SBCS字符串由一个零字节结尾,数据类型是char。

ASCII码:
计算机发明后,为了在计算机中表示字符,人们制定了一种编码,叫ASCII码。
ASCII码由一个字节中的7位(bit)表示,最高位空着,范围是0x00 - 0x7F 共128个字符。他们以为这128个数字就足够表示abcd…ABCD…1234…这些字符了。

扩展ASCII码:
咳…说英语的人就是“笨”!后来他们突然发现,如果需要按照表格方式打印这些字符的时候,缺少了“制表符”。于是又扩展了ASCII的定义,使用一个字节的全部8位(bit)来表示字符了,这就叫扩展ASCII码。范围是0x00-0xFF共256个字符。

多字节字符集(MBCS):

咳…说中文的人就是聪明!中国人利用连续2个扩展ASCII码的扩展区域(0xA0以后)来表示一个汉字,该方法的标准叫GB-2312(国标),之后又扩展出GBK和GB18030。后来,日文、韩文、阿拉伯文、台湾繁体…都使用类似的方法扩展了本地字符集的定义, 现在统一称为 MBCS字符集(多字节字符集,既用多个字节表示一个字符)。其实最常见的还是用2个字节表示一个字符,称为DBCS(双字节字符集)。此类常见字符集有gb2312(中国),big5(中国台湾地区),jis(日本)…。多字节字符集(MBCS)兼容单字节字符集(SBCS),通常并不区分他们。同SBCS一样,MBCS字符串也由一个零字节结尾,数据类型也是char。 但这个方法是有缺陷的,因为各个国家地区各自定义的字符集免不了会有交集。因此使用GB-2312的软件,就不能在BIG-5的环境下运行(显示乱码)。

ANSI编码:

为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符。比如:汉字 ‘中’ 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。
不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的编码标准。这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。
不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。
ANSI编码表示英文字符时用一个字节,表示中文用两个或四个字节。

宽字符集(Unicode字符集):

咳…说英语的人终于变“聪明”一些了。为了把全世界所有的文字符号都统一进行编码,于是制定了UNICODE字符集。标准的UNICODE字符集(即UCS-2,又称UTF-16)规定使用2个字节表示一个字符,这下终于好啦,全世界任何一个地区的软件,可以不用修改地就能在另一个地区运行了。Unicode字符数据类型有:WCHAR、_wchar_t、OLECHAR。
举个例子,假如你编写了一个Unicode的软件,它显示一个字符串”中国,崛起!”,然后你把这个软件拿到日本去,日本人运行看到的也是”中国,崛起!”,只不过他不一定看的懂(不认识中文),但至少不会像MBCS字符集那样是乱码。
但是,标准的UTF-16并不兼容ASCII编码(在基于ascii的编码方案中,一个8位的0x0总是表示一个字符串的结束的,而UTF-16则不然,它的一个字符完全有可能在高8位或者低8位上等于0x0,这会导致很多应用程序错误,尤其是在网络传输协议当中可能导致大量的字符串错误截断)。
为了兼容ASCII编码并方便数据的传输,后来又提出了UTF-8新方案,UTF-8用1到6位(注意不是字节)的变长字节(究竟多少字节不确定)表示一个字符,并且变长字节也最大限度节约了数据占用的字节数。再后来扩展方案UTF-32也提出来了,它用4个字节表示一个字符(这个用的少不管了)。

通常开发环境默认的就使用多字节字符集(MBCS)之一,比如我们中国的默认就使用GB2312字符集,毕竟它是本地字符集,比Unicode字符集(外来的和尚)更常用。Unicode常用于COM和Windows NT内。又因为ASCII字符集被兼容,可以认为在我们的程序中不是使用的MBCS字符集就是Unicode。

2.字符集的构成:Charset + Encoding

字符集包括两部分:字符的集合(Charset)和编码方案(Encoding)。字符的集(Charset)定义了该字符集内所有的字符本身;编码方案(Encoding)定义了在计算机上表示这些字符的规范(每个字符占几个字节等等问题)。
通常当我们提到GB2312时,是说字符集合是GB2312的,编码方案也是GB2312的,简单的情况的确如此,字符集等于编码,编码等于字符集。但Unicode是个例外,因为虽然Unicode的字符集合只有一个:Unicode字符集(Charset),但是编码方案它有多个:UTF-8,UTF-16(标准方案),UTF-32都是。因此,我们必须明确一个概念,UTF-8是 unicode字符集的一个编码方案,当我们在说到UTF-8字符和Unicode字符的时候,在某些情况下,它们在逻辑上是等价的,但是,他们并不是同一个东西,因为Unicode字符在二进制上还有一个选择就是原生的UTF-16编码。

3.代码页

然后,需要解释一下Codepage-代码页,百度百科上说代码页是字符集编码的别名。你在安装比如Window操作系统的时候若干代码也会随之安装到电脑上,比如codepage936代码页是简体中文,codepage950代码页是繁体中文,codepage932代码页是日文…,对于我们来说codepage936简体中文代码页就是电脑上默认使用的。
再具体说codepage实际是一个从unicode到其他mbcs的转换索引表,我们知道,windows操作系统是完全基于unicode的,正是通过代码页应用程序可以在unicode和本地字符集(如gb2312)之间来回转换。
举个例子,如果我们写了下面的程序:

#include <windows.h>
#include <stdio.h>

int main( void )
{
  SetConsoleOutputCP(936); //指定程序使用的代码页,我们中国默认使用936
  printf("简体中文\n");
  return 0;
}

程序运行结果显示正常:简体中文;
如果我们将main内的第一行的936改成其他的比如437(美国英语),那么将会显示乱码。
原因是程序在编译链接后生成的exe文件内全是01二进制数据,而这些二进制数据正是按Unicode编码方式保存下来的。就是说当编译器看到”简体中文”这个字符串,它会将这4个字符按程序当前使用的代码页(默认936,可在程序中指定其他的)映射成一串Unicode码01110…之类的保存到exe内。然后当我们运行exe时,Windows系统再将exe内的那串Unicode根据操作系统默认的代码页(也是936)再从Unicode映射回本地字符集。

4.程序中使用各种字符集

const char * p = "Hello"; // 使用 ASCII 字符集 
const char * p = "你好";  // 使用 MBCS 字符集,由于 MBCS 完全兼容 ASCII,多数情况下,我们并不严格区分他们 
LPCSTR p = "Hello,你好";  // 意义同上 

const WCHAR * p = L"Hello,你好"; // 使用 UNICODE 字符集(L用来定义UNICODE字符串,L就是转换成宽字符)
LPCOLESTR p = L"Hello,你好";     // 意义同上 

const TCHAR * p = _T("Hello,你好"); // 如果预定义了_UNICODE,则表示使用UNICODE字符集;如果定义了_MBCS,则表示使用 
LPCTSTR p = _T("Hello,你好");       // 意义同上 

  在上面的例子中,T是非常有意思的一个符号(TCHAR、LPCTSTR、LPTSTR、_T()、TEXT()、_TEXT()…),它表示使用一种中间类型,既不明确表示使用 MBCS,也不明确表示使用 UNICODE。那到底使用哪种字符集那?嘿嘿…编译的时候决定吧。设置条件编译的方式是:VC6中,”Project\Settings…\C/C++卡片 Preprocessor definitions” 中添加或修改_MBCS、_UNICODE。为了程序的可移植性,建议使用T类型!

转载:http://blog.sina.com.cn/s/blog_694aab1b0100rauw.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值