Windows上MBCS和UTF-8之间的差异
我正在读有关Windows上的字符集和编码。我注意到VisualStudio编译器(用于C++)中有两个编译器标志,分别称为MBCS和UNICODE。他们之间有什么区别?我不明白的是UTF-8在概念上与MBCS编码有何不同?此外,我在中发现以下引用: Unicode是一种16位字符编码Windows上MBCS和UTF-8之间的差异,windows,unicode,character-encoding,mbcs,Windows,Unicode,Character Encoding,Mbcs,我正在读有关Windows上的字符集和编码。我注意到VisualStudio编译器(用于C++)中有两个编译器标志,分别称为MBCS和UNICODE。他们之间有什么区别?我不明白的是UTF-8在概念上与MBCS编码有何不同?此外,我在中发现以下引用: Unicode是一种16位字符编码 这否定了我读到的关于Unicode的任何内容。我认为unicode可以使用不同的编码,比如UTF-8和UTF-16。有人能解释一下这种混淆吗?MBCS表示并描述任何字符集,其中字符编码(可能)超过1字节 ANSI
这否定了我读到的关于Unicode的任何内容。我认为unicode可以使用不同的编码,比如UTF-8和UTF-16。有人能解释一下这种混淆吗?MBCS表示并描述任何字符集,其中字符编码(可能)超过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字节
U+000000
高达U+10FFFF
我注意到有两个编译器
Visual Studio编译器中的标志(用于
C++)称为MBCS和UNICODE。是什么
他们之间有什么区别
Windows API中的许多函数有两个版本:一个接受char
参数(在特定于语言环境的代码页中),另一个接受wchar\t
参数(在UTF-16中)
每个函数对都有一个不带后缀的宏,这取决于是否定义了UNICODE
宏
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif
为了实现这一点,定义了TCHAR
类型来抽象API函数使用的字符类型
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
然而,这。您应该始终明确指定字符类型
我不明白的是UTF-8是怎样的
概念上不同于MBCS
编码
MBCS代表“多字节字符集”。从字面上看,UTF-8似乎符合条件
但在Windows中,“MBCS”仅指可以和Windows API函数的“A”版本一起使用的字符编码。这包括代码页932(Shift_JIS)、936(GBK)、949(KS_C_5601-1987)和950(Big5),但不是UTF-8
要使用UTF-8,必须使用MultiByteToWideChar
将字符串转换为UTF-16,调用函数的“W”版本,并在输出上调用WideCharToMultiByte
。这基本上就是“A”函数的实际功能,这让我很好奇
由于无法提供支持,Windows API的“A”版变得毫无用处。因此,您应该始终使用“W”功能
Unicode是一种16位字符编码
这否定了我读到的关于
Unicode
MSDN是错误的。Unicode是一种21位编码字符集,具有多种编码,最常见的是UTF-8、UTF-16和UTF-32。(还有其他Unicode编码,如GB18030、UTF-7和UTF-EBCDIC。)
每当微软提到“Unicode”时,他们实际上是指UTF-16(或UCS-2)。这是出于历史原因。Windows NT是Unicode的早期采用者,当时16位被认为对每个人来说都足够了,UTF-8仅用于计划9。因此UCS-2是Unicode。MBCS和Unicode是决定调用哪个版本的TCHAR.H例程的宏。例如,如果使用
\u tcsclen
计算字符串的长度,预处理器将根据以下两个宏将\u tcsclen
映射到不同的版本:\u MBCS和\u 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"));
结果将是463
以下是I的十六进制表示形式爱你M
单位为GBK
GBK: 49 B0 AE C4 E3 4D 00
_mbslen知道这个字符串是用GBK编码的,所以它可以正确地解释字符串并得到正确的结果4
words:49
asI
,B0 AE
as爱代码>,C4 E3
as你代码>,4D
为M
strlen只知道0x00
,所以它得到6
WCSCLIN将该十六进制数组编码在UTF16LE中,将两个字节作为一个字进行计数,得到<代码> 3 单词:<代码> 49 B0,<代码> AE C4,<代码> E34D。p>
正如@xiaokaoy所指出的,wcslen
的唯一有效终止符是00
。因此,如果以下字节不是00
,则结果不能保证为3
。作为其他答案的脚注,MSDN有一个带有方便表格的文档,总结了预处理器指令UNICODE和MBCS如何更改不同C/C++类型的定义
至于“Unicode”和“多字节字符集”的措辞,人们已经描述了其效果。我只想强调的是,这两个都是微软为一些非常具体的事情说话。(也就是说,如果对文本国际化的理解不是微软特有的,那么它们对Windows的意义就没有人们想象的那么普遍和特殊了。)这些确切的短语会出现,并且往往会有自己的separa
GBK: 49 B0 AE C4 E3 4D 00