Visual Studio 字符集 'Not set' vs 'Multi byte character set'



我正在使用一个遗留应用程序,我试图找出Character Set选项下使用Multi byte character setNot Set编译的应用程序之间的差异。

我理解用Multi byte character set编译定义_MBCS,允许使用多字节字符集代码页,使用Not set不定义_MBCS,在这种情况下只允许使用单字节字符集代码页。

在使用Not Set的情况下,我假设我们只能使用本页上找到的单字节字符集代码页:http://msdn.microsoft.com/en-gb/goglobal/bb964654.aspx

因此,我是否正确地认为使用Not Set,应用程序将无法编码和写入或读取远东语言,因为它们是在双字节字符集代码页(当然还有Unicode)中定义的?

接下去,如果定义了Multi byte character集合,是单字节和多字节字符集代码页都可用,还是只有多字节字符集代码页?我猜必须同时支持欧洲语言。

谢谢,安迪

进一步阅读

这些页面上的答案没有回答我的问题,但有助于我的理解:关于"字符集"visual studio 2010中的选项

所以,正如工作研究…我的语言环境设置为日语

硬编码字符串的影响

char *foo = "Jap text: テスト";
wchar_t *bar = L"Jap text: テスト";

使用Unicode编译

* bar = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (Code page 932)
*bar = 4a 00 61 00 70 000 2000 74 00 65 78 74 00 3a 00 2000 c6 30 b9 30 c8 30 == UTF-16或UCS-2

使用Multi byte character set编译

* bar = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (Code page 932)
*bar = 4a 00 61 00 70 000 2000 74 00 65 78 74 00 3a 00 2000 c6 30 b9 30 c8 30 == UTF-16或UCS-2

使用Not Set编译

* bar = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (Code page 932)
*bar = 4a 00 61 00 70 000 2000 74 00 65 78 74 00 3a 00 2000 c6 30 b9 30 c8 30 == UTF-16或UCS-2

结论:字符编码对硬编码字符串没有任何影响。尽管如上所述定义字符似乎使用了Locale定义的代码页,而wchar_t似乎使用了UCS-2或UTF-16。

在Win32 api的W/A版本中使用编码字符串

所以,使用下面的代码:
char *foo = "C:\Temp\テスト\テa.txt";
wchar_t *bar = L"C:\Temp\テスト\テw.txt";
CreateFileA(bar, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
CreateFileW(foo, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

使用Unicode编译

结果:两个文件都创建了

使用Multi byte character set编译

结果:两个文件都创建了

使用Not set编译

结果:两个文件都创建了

结论:无论选择的字符集如何,AW版本的API都期望使用相同的编码。由此,也许我们可以假设Character Set选项所做的只是在API的版本之间进行切换。因此,A版本总是期望当前代码页编码中的字符串,而W版本总是期望UTF-16或UCS-2。

使用Win32 api打开文件

所以使用下面的代码:

char filea[MAX_PATH] = {0};
OPENFILENAMEA ofna = {0};
ofna.lStructSize = sizeof ( ofna );
ofna.hwndOwner = NULL  ;
ofna.lpstrFile = filea ;
ofna.nMaxFile = MAX_PATH;
ofna.lpstrFilter = "All*.*Text*.TXT";
ofna.nFilterIndex =1;
ofna.lpstrFileTitle = NULL ;
ofna.nMaxFileTitle = 0 ;
ofna.lpstrInitialDir=NULL ;
ofna.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ;  
wchar_t filew[MAX_PATH] = {0};
OPENFILENAMEW ofnw = {0};
ofnw.lStructSize = sizeof ( ofnw );
ofnw.hwndOwner = NULL  ;
ofnw.lpstrFile = filew ;
ofnw.nMaxFile = MAX_PATH;
ofnw.lpstrFilter = L"All*.*Text*.TXT";
ofnw.nFilterIndex =1;
ofnw.lpstrFileTitle = NULL;
ofnw.nMaxFileTitle = 0 ;
ofnw.lpstrInitialDir=NULL ;
ofnw.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ;
GetOpenFileNameA(&ofna);
GetOpenFileNameW(&ofnw);

并选择:

  • C:Temp open .txt
  • C:Temp open .txt

收益率:

当使用Unicode

编译时

*filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 83 67 5c 83 65 6f 70 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis(代码页932)
* filea = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 000 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 000 65 00 6e 00 77 00 2e 00 74 000 78 7400 == UTF-16或UCS-2

当使用Multi byte character set

编译时

*filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 83 67 5c 83 65 6f 70 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis(代码页932)
* filea = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 000 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 000 65 00 6e 00 77 00 2e 00 74 000 78 7400 == UTF-16或UCS-2

使用Not Set编译时

*filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 83 67 5c 83 65 6f 70 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis(代码页932)
* filea = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 000 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 000 65 00 6e 00 77 00 2e 00 74 000 78 7400 == UTF-16或UCS-2

结论:再次,Character Set设置对Win32 API的行为没有影响。A版本似乎总是返回一个具有活动代码页编码的字符串,而W版本总是返回UTF-16或UCS-2。我可以在这个很棒的答案中看到一些解释:https://stackoverflow.com/a/3299860/187100.

最终并

Hans似乎是正确的,当他说这个定义并没有真正的魔法,除了改变Win32 api使用WA。因此,我看不出Not SetMulti byte character set有什么区别。

不,这不是真正的工作方式。唯一发生的事情是宏被定义了,否则它不会对编译器产生神奇的影响。使用#ifdef _MBCS来测试这个宏的代码是非常少见的。

您几乎总是把它留给辅助函数来进行转换。像WideCharToMultiByte(), OLE2A()或wctombs()。按照代码页的指导,它们是始终考虑多字节编码的转换函数。_MBCS是一个历史上的偶然事件,仅在25年前多字节编码还不常见的时候才与之相关。就像使用非unicode编码一样,现在也是历史的产物。

参考资料中指出:

根据定义,ASCII字符集是所有字符集的子集multibyte-character集。在许多多字节字符集中,每个0x00 - 0x7F范围内的字符与在ASCII字符集中具有相同的值。例如,在两者中ASCII和MBCS字符串,1字节的NULL字符('')具有值0x00,表示结束空字符。

正如你所猜测的,通过启用_MBCS, Visual Studio也支持ASCII单字符集。

在第二个参考中,即使我们启用了_MBCS:

,似乎也支持单个字符集。

MBCS/Unicode可移植性:使用char.h头文件,您可以构建来自相同来源的单字节、MBCS和Unicode应用程序。h定义了以_tcs为前缀的宏,它们映射到str、_mbs或WCS功能,如适用。要构建MBCS,请定义符号_MBCS。要构建Unicode,请定义符号_UNICODE。缺省情况下,_MBCS为为MFC应用程序定义的。有关更多信息,请参见通用文本

最新更新