我一直在处理一个遗留应用程序,试图弄清楚使用 Multi byte character set
和 Not 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
set,那么单字节和多字节字符集代码页都可用,还是只有多字节字符集代码页可用?我猜测两者都可以支持欧洲语言。
谢谢,
Andy
进一步阅读
以下页面的答案没有回答我的问题,但有助于我理解:关于 Visual Studio 2010 中的“字符集”选项
研究
因此,只是作为工作研究...将我的区域设置为日语
对硬编码字符串的影响
char *foo = "Jap text: テスト";
wchar_t *bar = L"Jap text: テスト";
使用Unicode编译:
*foo = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (代码页932)
*bar = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 c6 30 b9 30 c8 30 == UTF-16或UCS-2
使用多字节字符集编译:
*foo = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (代码页932)
*bar = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 c6 30 b9 30 c8 30 == UTF-16或UCS-2
编译时未设置字符集:
*foo = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (代码页932)
*bar = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 c6 30 b9 30 c8 30 == UTF-16或UCS-2
结论: 字符编码对硬编码字符串没有影响。虽然上述定义的char似乎使用了定义的本地代码页,而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
进行编译:
结果:两个文件都被创建
使用 多字节字符集
进行编译:
结果:两个文件都被创建
使用 未设置
进行编译:
结果:两个文件都被创建
结论:
无论选择哪种字符集,API 的 A
版本和 W
版本都期望相同的编码。因此,我们可以假设 字符集
选项只是在 API 版本之间进行切换。因此,A
版本始终期望当前代码页编码的字符串,而 W
版本始终期望 UTF-16 或 UCS-2 编码。
使用 W 和 A Win32 APIs 打开文件
因此,可以使用以下代码:
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\0*.*\0Text\0*.TXT\0";
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\0*.*\0Text\0*.TXT\0";
ofnw.nFilterIndex =1;
ofnw.lpstrFileTitle = NULL;
ofnw.nMaxFileTitle = 0 ;
ofnw.lpstrInitialDir=NULL ;
ofnw.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ;
GetOpenFileNameA(&ofna);
GetOpenFileNameW(&ofnw);
并选择其中之一:
- C:\Temp\テスト\テopenw.txt
- C:\Temp\テスト\テopenw.txt
结果为:
当使用Unicode
编译时
*filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis(代码页932)
*filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16或UCS-2
当使用Multi byte character set
编译时
*filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis(代码页932)
*filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16或UCS-2
当使用Not Set
编译时
*filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis (Code page 932)
*filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16 or UCS-2
结论:
再次强调,字符集
设置与Win32 API的行为无关。 A
版本似乎始终返回具有活动代码页编码的字符串,而W
则始终返回UTF-16或UCS-2编码。我在这个很好的答案中实际上可以看到这种解释: https://dev59.com/L3A75IYBdhLWcg3wbojM#3299860.
最终结论
当Hans说到定义实际上没有任何魔力时,他似乎是正确的,除了将Win32 API更改为使用W
或A
之外,它并没有发生什么变化。因此,我无法真正看到未设置
和多字节字符集
之间的任何区别。