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的环境下运行(显示乱码)。

 

宽字符集(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类型!

 

说明:

1. .NET 的平台CLR (Common Language RunTime库中用定义(#define) _UNICODE 来表示使用Unicode,在Win32 API中是用定义(#define) UNICODE 来表示使用 Unicode。而大多数应用程序(Application)都是既使用CLR又使用Win32 API,再如宏_T根据_UNICODE定义与否来区分,而宏TEXT则根据UNICODE区分。 所以一般地,_UNICODE和UNICODE 应该在工程设置中同时定义或同时不定义。

2. 关于BSTR的使用:http://www.vckbase.com/document/viewdoc/?id=1911

参考:

http://hi.baidu.com/atgc123/blog/item/0e394e1fe3e7c1fe19d57667.html

http://hi.baidu.com/windtrace/blog/item/fe4879ec73a42dde2f2e21fc.html

http://ltzmage.blog.163.com/blog/static/1796999820100144179987/

http://blog.163.com/xu_chao2000/blog/static/27770610200802005230435/

http://zhidao.baidu.com/question/247158007.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用多字节字符集 (MBCS) 或者 Unicode 字符集来进行转换,你可以使用一些 C++ 标准库提供的函数来实现。 如果你想将一个窄字符字符串 (char *) 转换为宽字符字符串 (LPCWSTR),你可以使用 MultiByteToWideChar 函数。以下是一个示例代码: ```cpp #include <windows.h> #include <iostream> int main() { const char* narrowStr = "Hello, World!"; // 窄字符字符串 int wideStrLength = MultiByteToWideChar(CP_UTF8, 0, narrowStr, -1, NULL, 0); // 获取宽字符字符串的长度 wchar_t* wideStr = new wchar_t[wideStrLength]; // 分配内存来存储宽字符字符串 MultiByteToWideChar(CP_UTF8, 0, narrowStr, -1, wideStr, wideStrLength); // 执行转换 // 打印宽字符字符串 std::wcout << wideStr << std::endl; delete[] wideStr; // 释放内存 return 0; } ``` 如果你想将一个宽字符字符串 (LPCWSTR) 转换为窄字符字符串 (char *),你可以使用 WideCharToMultiByte 函数。以下是一个示例代码: ```cpp #include <windows.h> #include <iostream> int main() { LPCWSTR wideStr = L"Hello, World!"; // 宽字符字符串 int narrowStrLength = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, NULL, 0, NULL, NULL); // 获取窄字符字符串的长度 char* narrowStr = new char[narrowStrLength]; // 分配内存来存储窄字符字符串 WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, narrowStr, narrowStrLength, NULL, NULL); // 执行转换 // 打印窄字符字符串 std::cout << narrowStr << std::endl; delete[] narrowStr; // 释放内存 return 0; } ``` 这些示例代码演示了如何使用 Windows API 函数来进行字符串的转换。请确保在使用这些函数之前,包含了 `<windows.h>` 头文件。 希望这能帮助你进行字符集转换!如果你有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值