Visual Studio 字符集 'Not set' vs 'Multi byte character set'
Visual Studio Character Sets 'Not set' vs 'Multi byte character set'
我正在使用一个遗留应用程序,我试图找出Character Set
选项下使用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
集合,是单字节和多字节字符集代码页都可用,还是只有多字节字符集代码页?我猜必须同时支持欧洲语言。
谢谢,安迪
进一步阅读
这些页面上的答案没有回答我的问题,但有助于我的理解:关于"字符集"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
编译
结果:两个文件都创建了
结论:无论选择的字符集如何,A
和W
版本的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使用W
或A
。因此,我看不出Not Set
和Multi 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应用程序定义的。有关更多信息,请参见通用文本
- 为什么我无法更改"set<set>"循环中的值<int>
- 对于set上的循环-获取next元素迭代器
- 在声明中合并两个常量"std::set"(不是在运行时)
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将 std::set 与基于键的比较器一起使用
- 如何使用set实现无序数据结构?
- 可视化C++:发布模式的运行时库作为'Multi-threaded Debug DLL'
- 使用运算符调用 void 函数时出错<set>
- 修改"std::set"中用户定义类型的值
- 生成提升::hana::set 的常量表达式问题
- 如何在构造函数参数中初始化"std::set"?
- 如何使用 lower_bound/upper_bound 从 std::set 获取索引号?
- 如何在 C++ 中转发声明 std::set?
- 重构使用动态强制转换的 std::set 的比较运算符
- set::find 查找不存在的元素
- 为什么 std::set.erase(first, last) 会影响从中获取 (first, last) 的容器?
- 将 std:set<int32_t> 复制到 std::set <uint32_t>的好方法
- 错误 C2676:std::set::const_iterator 没有运算符 + 函数?
- std::set 是否将对象连续存储在内存中?
- Visual Studio 字符集 'Not set' vs 'Multi byte character set'