我习惯处理ASCII字符串但是现在使用UNICODE我对某些术语太过困惑了:
什么是多字节字符,什么是alphabet
有什么区别?
多字节是指内存中包含多个字节的字符,而widechar
只是表示它的数据类型吗?
widechar
和MultiByteToWideChar
?如果我宣布这样的话:
WideCharToMultiByte
如果我定义了wchar_t* wcMsg = L"مرحبا";
MessageBoxW(0, wcMsg, 0, 0);
,它会正确打印消息但是为什么我没有从UNICODE
转换到这里
我的项目中的字符集有什么区别:WideCharToMultiByte
和_MBCS
?
MSDN让我误以为“Windows API”的最后一件事是UTF-16。
任何人都可以用一些例子来解释。非常感谢您的澄清。
答案 0 :(得分:4)
ASCII字符串的字符宽度为一个字节(通常为8位,很少为7,9或其他位宽)。这是当时的遗留问题,当内存大小非常小且昂贵时,处理器通常每条指令只能处理一个字节。
由于很容易想象,到目前为止,一个字节还不足以存储世界上所有可用的字形。仅中国就有87,000个字形。 char通常只能处理256个字形(以8位字节为单位)。 ASCII仅定义了96个字形(加上较低的32个字符,它们被定义为不可打印的控制字符)。这对于英语上下字符,数字以及一些插值和其他字形来说已经足够了。
要处理比一个字节可以容纳的字形更多的字形,一种方法是将基本字形存储在一个字节中,将其他常见字形存储在两个字节中,并且很少使用3个甚至更多字节中的字形。这种方法称为Multi byte char set or Variable-width encoding。一个非常常见的例子是UTF 8,它对一个字符使用一个最多4个字节。它将ASCII字符集存储在一个字节中(因此它也向后兼容ASCII)。最高位被定义为一个开关:如果它被设置,其他字节将跟随。这同样适用于以下字节,因此"链"形成最多4个字节。 可变宽度字符集的专业人员是:
缺点是:
myString[n]
提供一个字形;相反,如果跟随更多字节,则必须评估每个字节。另一种方法是将每个字符存储在由n个字节组成的固定长度字中,该字宽足以容纳所有可能的字形。这称为固定宽度字符集;所有字符都有相同的宽度。一个众所周知的例子是UTF32。它是32位宽,可以在一个单词中存储所有可能的字符。固定宽度字符集的专业人员和内容显然与可变宽度字符集相反:内存繁重但更容易迭代。
但是,即使在UTF32可用之前,微软也选择了他们的原生字符集:他们使用UTF16作为Windows的字符集,它使用至少2个字节(16位)的字长。这足以存储比单字节字符集更多的字形,但不是全部。考虑到这一点,微软在多字节"多字节"之间进行区分。和" Unicode"今天有点误导,因为它们的unicode实现也是一个多字节字符集 - 只有一个字形的最小大小。有人说这是一个很好的妥协,有人说它是两个世界中最糟糕的 - 无论如何,这就是它的方式。那时(Windows NT)它是唯一可用的Unicode字符集,从这个角度来看,它们在多字符和Unicode之间的区别当时是正确的(参见Raymond Chen的评论)
当然,如果你想将一个字符串中的字符串(让我们说UTF8)转换成另一个字符串(让我们说UTF16),你必须转换它们。这是MultiByteToWideChar
为你做的事情,WideCharToMultiByte
反之亦然。还有一些其他的转换函数和库。
这种转换花费了相当多的时间,因此结论是:如果你大量使用字符串和系统调用,为了性能,你应该使用操作系统的本机字符集,在你的情况下是UTF16
因此,对于字符串处理,您应该选择wchar_t
,如果是Windows则表示UTF16。不幸的是,wchar_t
的宽度可能因编译器而异;在Unix下它通常是UTF32,在Windows下它是UTF16。
_MBCS
是一个自动预处理器定义,它告诉您已将字符集定义为多字节,UNICODE
告诉您已将其设置为UTF16。
你可以写
wchar_t* wcMsg = L"مرحبا";
MessageBoxW(0, wcMsg, 0, 0);
即使在没有UNICODE
定义集的程序中也是如此。 L"
前缀定义了您的字符串是UNICODE
(宽字符)字符串,您可以使用它调用系统函数。
不幸的是你不能写
char* msg = u8"مرحبا";
MessageBoxA(0, msg, 0, 0);
C ++ 11中的字符集支持已得到改进,因此您还可以通过前缀u8
将字符串定义为UTF8。但窗口的功能是" A"后缀并不了解UTF8。
(另见https://stackoverflow.com/a/504789/2328447)
这也建议在Windows / Visual Studio下使用UTF16 aka UNICODE。
将项目设置为"使用多字节字符集"或"使用Unicode字符集"还会更改许多其他字符相关定义:最常见的是宏TCHAR
,_T()
以及所有不依赖于后缀的字符串相关Windows函数,例如: MessageBox()
(没有W
或A
后缀)
如果您将项目设置为"使用多字节字符集",TCHAR
将扩展为char
,_T()
将展开为空,Windows功能将获得附加A
后缀。
如果您将项目设置为"使用Unicode字符集",TCHAR
将扩展为wchar_t
,_T()
将扩展为L
前缀,并且Windows函数将附加W
后缀。
这意味着,写作
TCHAR* msg = _T("Hello");
MessageBox(0, msg, 0, 0);
将使用多字节字符集或unicode集进行编译。您可以在MSDN找到有关这些主题的综合指南。
不幸的是
TCHAR* msg = _T("مرحبا");
MessageBox(0, msg, 0, 0);
当"使用多字节字符集时,仍然无法工作"被选中 - Windows函数仍然不支持UTF8,你甚至会得到一些编译器警告,因为你已经定义了unicode字符,这些字符包含在未标记为Unicode的字符串中(_T()
不会扩展到u8
)