windows - ansi编码 - utf 8 bom区别



Windows上MBCS和UTF-8的区别 (3)

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

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

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

然而,这是个坏主意 。 您应该始终明确指定字符类型。

我没有得到的是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不仅仅支持UTF-8

这种无法支持最常见的字符编码使得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仅用于Plan 9.所以UCS-2 Unicode。

https://ffff65535.com

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

Unicode是一种16位字符编码

这否定了我读到的关于Unicode的任何内容。 我认为unicode可以使用不同的编码进行编码,例如UTF-8和UTF-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

这是I爱你M在GBK中的十六进制表示。

GBK:             49 B0 AE C4 E3 4D 00                

_mbslen知道这个字符串是用GBK编码的,所以它可以正确地解释字符串并得到正确的结果4字: 49IB0 AEC4 E34DM

strlen只知道0x00 ,所以得到6

wcslen认为这个hexdeciaml数组是用UTF16LE编码的,它将两个字节计为一个字,所以得到3字: 49 B0AE C4E3 4D

正如@xiaokaoy指出的那样, wcslen唯一有效的终结符是00 00 。 因此,如果后续字节不是00则结果不保证为3


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

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





mbcs