最后,使用C标准库的printf函数输出窄字符串和宽字符串——
// Cprintf("\nC:\n");printf("\t%s\n", psa);printf("\t%ls\n", psw);
所以,测试程序的运行结果应当为——
A汉字ABC
W汉字ABCC:A汉字ABCW汉字ABC
注意为了更好区分C++标准IO库与C标准库的输出结果,这里给printf加了个TAB字符。
二、测试VC2005
因VC2005是VC系列中第一个对C++03标准支持性较好的编译器,先来测测它。
2.1 Debug版
在VC2005中以Debug模式编译测试程序,执行结果为——
可见C++的cout、wcout均无法正常输出中文字符。
而C的printf都能正常输出含中文字符的窄字符串与宽字符串。
2.2 Release版
将编译配置改为“Release”模式,再编译运行,神奇的事情发生了。执行结果为——
A汉字ABC
W汉字ABCC:A汉字ABCW汉字ABC
Release版下全部通过,cout、wcout、printf均能正常输出。
三、测试VC2008及更高版本的VC
在VC2008中编译测试程序,执行结果为——
A汉字ABC
W汉字ABCC:A汉字ABCW汉字ABC
全部通过,cout、wcout、printf均能正常输出。然后测试了Release版,也是全部通过。看来VC2005的Bug已经被修正了。
随后又测试了VC2010、VC2012,均是全部通过。
四、测试Windows中的MinGW 4.1 测试
使用GCC 4.6.2(MinGW(20120426))编译测试程序,执行结果为——
窄字符串都能正常输出,但宽字符串都不能正常输出。
4.2 修改代码,使MinGW能正常显示
将初始化代码增加一行——
// init.locale::global(locale(""));setlocale(LC_CTYPE, ""); // MinGW gcc.wcout.imbue(locale(""));
再用MinGW编译运行,执行结果为——
A汉字ABC
W汉字ABCC:A汉字ABCW汉字ABC
全部通过了,cout、wcout、printf均能正常输出。看来MinGW中的“locale::global(locale(""))”不会设置“setlocale(LC_ALL, "")”,必须手动调用。
用VC2008编译刚才修改后的代码,也是全部通过。多调用一次“setlocale(LC_ALL, "")”并不会造成破坏。
五、测试Linux下的gcc 5.1 测试
使用Linxu中的GCC编译测试程序,执行结果为——
A汉字ABC
WIWABCC:A汉字ABCW汉字ABC
cout、printf均能正常输出,但wcout不能正常输出。
5.2 修改代码,使Linux下能正常显示
将初始化代码增加一行——
// init.ios::sync_with_stdio(false); // Linux gcc.locale::global(locale(""));wcout.imbue(locale(""));
再用gcc编译运行,执行结果为——
A汉字ABC
W汉字ABCC:A汉字ABCW汉字ABC
全部通过了,cout、wcout、printf均能正常输出。
5.3 第2次修改代码,使MinGW能正常显示
切换回Windows,使用MinGW编译刚才修改后的代码,执行结果为——
宽字符串又不能正常显示了。
根据上次的经验,将初始化代码增加“setlocale”——
// init.ios::sync_with_stdio(false); // Linux gcc.locale::global(locale(""));setlocale(LC_CTYPE, ""); // MinGW gcc.wcout.imbue(locale(""));
再用MinGW编译运行,执行结果为——
A汉字ABC
W汉字ABCC:A汉字ABCW汉字ABC
终于全部通过了。
5.4 在Linux中测试第2次修改代码
在Linux中测试第2次修改代码,全部通过。
再用VC2008编译刚才修改后的代码,也是全部通过。
看来终于找到VC、MinGW、Linux下均有效的初始化方法了。可惜“ios::sync_with_stdio(false)”禁用同步后需要手动进行同步,会造成某些旧代码工作不正常,该方法实用性不大。
六、测试Mac OSX下的gcc
使用Linxu中的GCC编译测试程序,执行结果为——
这么简单的程序,居然运行时报错了。这是什么原因呢?
用gdb调试该程序。r运行,where显示调用栈,list显示源码——
可以看出,是在执行“locale("")”时报错的。
“locale("")”不是C++标准中规定的吗,怎么连它都会报错?
在网上搜索了一下,发现有人查过mac下的gcc源码,它在注释中明确写了"Currently, the generic model only supports the "C" locale."——
http://stackoverflow.com/questions/1745045/stdlocale-breakage-on-macos-10-6-with-lang-en-us-utf-8
std::locale breakage on MacOS 10.6 with LANG=en_US.UTF-8
七、总结
虽然C++标准的设想十分完善,可惜各种编译器的实现程度存在不少差异。甚至某些平台上连“locale("")”都不支持。
为了保证跨平台,慎用C++标准IO库,最好尽可能的使用兼容性非常好的C标准库。
参考文献——
《ISO/IEC 9899:1999》(C99). ISO/IEC,1999. www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
《C++ International Standard - ISO IEC 14882 Second edition 2003》(C++03). ISO/IEC,2003-10-15.
《C++标准程序库—自修教程与参考手册》. Nicolai M.Josuttis 著,侯捷、孟岩 译. 华中科技大学出版社,2002-09.
《std::locale breakage on MacOS 10.6 with LANG=en_US.UTF-8》. http://stackoverflow.com/questions/1745045/stdlocale-breakage-on-macos-10-6-with-lang-en-us-utf-8
《[C] 跨平台使用TCHAR——让Linux等平台也支持tchar.h,解决跨平台时的格式控制字符问题,多国语言的同时显示》. http://www.cnblogs.com/zyl910/archive/2013/01/17/tcharall.html
源码下载——
http://files.cnblogs.com/zyl910/wchar_crtbug.rar