Windows上MBCS和UTF-8的区别

时间:2010-07-21 11:11:12

标签: windows unicode character-encoding mbcs

我正在阅读关于Windows上的字符集和编码。我注意到Visual Studio编译器(用于C ++)中有两个编译器标志,称为MBCS和UNICODE。他们之间有什么区别?我没有得到的是UTF-8在概念上与MBCS编码有何不同?另外,我在MSDN中找到了以下引用:

  

Unicode是一个16位字符编码

这否定了我读到的有关Unicode的内容。我认为unicode可以使用不同的编码进行编码,例如UTF-8和UTF-16。有人可以对这种混乱有所了解吗?

4 个答案:

答案 0 :(得分:97)

  

我注意到有两个编译器   Visual Studio编译器中的标志(for   C ++)称为MBCS和UNICODE。什么是   他们之间的区别?

Windows API中的许多函数有两个版本:一个采用char参数(在特定于语言环境的代码页中),另一个采用wchar_t参数(采用UTF-16)。 / p>

int MessageBoxA(HWND hWnd, const char* lpText, const char* lpCaption, unsigned int uType);
int MessageBoxW(HWND hWnd, const wchar_t* lpText, const wchar_t* lpCaption, unsigned int uType);

这些函数对中的每一个都有一个没有后缀的宏,这取决于是否定义了UNICODE宏。

#ifdef UNICODE
   #define MessageBox MessageBoxW
#else
   #define MessageBox MessageBoxA
#endif

为了使这项工作,TCHAR类型被定义为抽象出API函数使用的字符类型。

#ifdef UNICODE
    typedef wchar_t TCHAR;
#else
    typedef char TCHAR;
#endif

然而,was a bad idea。您应该始终明确指定字符类型。

  

我没有得到的是UTF-8是怎样的   概念上不同于MBCS   编码?

MBCS代表“多字节字符集”。对于字面意思,似乎UTF-8符合条件。

但在Windows中,“MBCS”仅指可与Windows API函数的“A”版本一起使用的字符编码。这包括代码页932(Shift_JIS),936(GBK),949(KS_C_5601-1987)和950(Big5),但 NOT UTF-8。

要使用UTF-8,您必须使用MultiByteToWideChar将字符串转换为UTF-16,调用函数的“W”版本,并在输出上调用WideCharToMultiByte。这基本上就是“A”函数的实际功能,这让我想起why Windows doesn't just support UTF-8

无法支持the most common character encoding使得Windows API的“A”版本无法使用。因此,您应始终使用“W”功能

  

Unicode是一个16位字符编码

     

这否定了我读到的任何内容   的Unicode。

MSDN错了。 Unicode是一个21位编码字符集,具有多种编码,最常见的是UTF-8,UTF-16和UTF-32。 (还有其他Unicode编码,例如GB18030,UTF-7和UTF-EBCDIC。)

每当Microsoft引用“Unicode”时,它们的确意味着UTF-16(或UCS-2)。这是出于历史原因。 Windows NT是Unicode的早期采用者,当16位被认为对每个人都足够时,UTF-8仅用于Plan 9.所以UCS-2 Unicode。

答案 1 :(得分:16)

_MBCS和_UNICODE是用于确定要调用哪个版本的TCHAR.H例程的宏。例如,如果使用_tcsclen来计算字符串的长度,则预处理器会根据两个宏将_tcsclen映射到不同的版本:_MBCS和_UNICODE。

_UNICODE & _MBCS Not Defined: strlen  
_MBCS Defined: _mbslen  
_UNICODE Defined: wcslen  

要解释这些字符串长度计数功能的不同,请考虑以下示例 如果您的计算机包运行使用GBK(936代码页)的Windows简体中文版,则编译一个gbk文件编码的源文件并运行它。

printf("%d\n", _mbslen((const unsigned char*)"I爱你M"));
printf("%d\n", strlen("I爱你M"));
printf("%d\n", wcslen((const wchar_t*)"I爱你M"));

结果为4 6 3

以下是GBK中I爱你M的十六进制表示。

GBK:             49 B0 AE C4 E3 4D 00                

_mbslen知道这个字符串是用GBK编码的,所以它可以正确地解释字符串并得到正确的结果4字:49IB0 AE为{ {1}},C4 E34D

strlen只知道M,因此得到0x00

wcslen认为这个hexdeciaml数组是以UTF16LE编码的,它将两个字节计为一个单词,因此得到6个单词:349 B0AE C4

正如@xiaokaoy所指出的,E3 4D唯一有效的终结符是wcslen。因此,如果以下字节不是00 00,则不保证结果为3

答案 2 :(得分:10)

MBCS 表示Multi-Byte Character Set,并描述将字符编码为(可能)超过1个字节的任何字符集。

ANSI / ASCII 字符集不是多字节的。

然而,

UTF-8 是一种多字节编码。它将任何Unicode字符编码为1,2,3或4个八位字节(字节)的序列。

但是,UTF-8只是Unicode字符集的几种可能的具体编码中的一种。值得注意的是,UTF-16是另一种,恰好是Windows / .NET(IIRC)使用的编码。这是UTF-8和UTF-16之间的区别:

  • UTF-8将任何Unicode字符编码为1,2,3或4个字节的序列。

  • UTF-16将大多数Unicode字符编码为2个字节,有些则编码为4个字节。

因此正确,Unicode是16位字符编码。它更类似于21位编码(或者甚至更多这些天),因为它包含一个代码点U+000000最多U+10FFFF的字符集。

答案 3 :(得分:4)

作为其他答案的脚注,MSDN有一个文档Generic-Text Mappings in TCHAR.H,其中包含方便的表格,总结了预处理程序指令_UNICODE和_MBCS如何更改不同C / C ++类型的定义。

对于短语“Unicode”和“多字节字符集”,人们已经描述了效果是什么。我只想强调一下,这些都是微软代表一些非常具体的事情。 (也就是说,如果来自非Microsoft特定的对文本国际化的理解,那么它们意味着不那么通用且比Windows更具特异性。)这些确切的短语出现并倾向于获得他们自己的单独部分/子部分微软技术文档,例如在Text and Strings in Visual C++