12

我正在使用旧版应用程序,并且正在尝试找出使用该选项编译的应用程序Multi byte character setNot Set使用该Character 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,单字节和多字节字符集代码页都可用,还是只有多字节字符集代码页?我猜它必须同时支持欧洲语言。

谢谢,

安迪

延伸阅读

这些页面上的答案没有回答我的问题,但有助于我的理解: 关于 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

编译Multi byte character set

*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

编译Not Set

*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

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

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

因此,使用以下代码:

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

结果:创建了两个文件

结论: 无论选择何种字符集,API的A和版本都期望相同的编码。W由此,也许我们可以假设所有Character Set选项都是在 API 版本之间切换。因此,该A版本始终需要当前代码页编码中的字符串,并且该W版本始终需要 UTF-16 或 UCS-2。

使用 W 和 A 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\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(代码页 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

结论: 同样,该Character Set设置与 Win32 API 的行为无关。该A版本似乎总是返回一个带有活动代码页编码的字符串,并且该版本W总是返回 UTF-16 或 UCS-2。我实际上可以在这个很好的答案中看到这一点:https ://stackoverflow.com/a/3299860/187100 。

终极结论

W汉斯似乎是正确的,他说除了将 Win32 API 更改为使用或之外,定义实际上并没有任何魔力ANot Set因此,我真的看不出和之间有什么区别Multi byte character set

4

2 回答 2

8

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

您几乎总是将其留给辅助函数来进行转换。像 WideCharToMultiByte()、OLE2A() 或 wctombs()。根据代码页的指导,它们是始终考虑多字节编码的转换函数。_MBCS 是一个历史性的意外,仅在 25 多年前才相关,当时多字节编码还不常见。就像现在使用非 Unicode 编码也是一种历史产物一样。

于 2013-07-19T11:33:51.767 回答
0

参考文献中指出:

根据定义,ASCII 字符集是所有多字节字符集的子集。在许多多字节字符集中,0x00 – 0x7F 范围内的每个字符都与 ASCII 字符集中具有相同值的字符相同。例如,在 ASCII 和 MBCS 字符串中,1 字节的 NULL 字符 ('\0') 的值为 0x00,表示终止的空字符。

如您所料,通过启用_MBCSVisual Studio 还支持ASCII单字符集。

在第二个参考中,即使我们启用,似乎也支持单个字符集_MBCS

MBCS/Unicode 可移植性: 使用 Tchar.h 头文件,您可以从相同的源构建单字节、MBCS 和 Unicode 应用程序。Tchar.h 定义了以 _tcs 为前缀的宏,它们根据需要映射到 str、_mbs 或 wcs 函数。要构建 MBCS,请定义符号 _MBCS。要构建 Unicode,请定义符号 _UNICODE。默认情况下,_MBCS 是为 MFC 应用程序定义的。有关详细信息,请参阅 Tchar.h 中的通用文本映射。

于 2013-07-19T10:00:42.040 回答