本来我已经参考网上关于C++中文输出乱码的文章解决了,如下面的代码输出前调用wcout.imbue
设置locale
,就可以正常输出中文了。
std::wcout.imbue(std::locale(std::locale(), "", LC_CTYPE));
std::wcout << L"江清月近人" << std::endl;
但是同样的方法换在另一个程序中还是输出乱码。反复查找原因,最后发现是两个源码的编码格式不同。虽然都是UTF-8,但是能正确输出中文的源码文件是带BOM头的,另一个是不带BOM的。参考这个篇文章《MSVC中C++ UTF8中文编码处理探究》搞明白了MSVC对于不带BOM的UTF-8文件,默认会根据本地locale的设置来决定文件的编码(对于简体中文系统,就是GBK)。所以会对于UTF-8 without BOM的代码文件输出中文就是乱码。对于UTF-8 with BOM文件,会正确将其按照UTF-8来识别。
/utf-8 编译选项
MSVC对于UTF-8 without BOM格式支持不好,这个问题由来已久,在VS2015之前的版本一直存在。
在VS2015版本(Visual Studio 2015 Update 2),增加一个编译选项/utf-8
,该编译选项的作用就是将源码字符集和执行文件字符集指定为UTF-8。增加该编译选项后,再重新编译运行,程序正确输出中文,问题解决。
参见微软官网:《/utf-8 (Set Source and Executable character sets to UTF-8)》
#pragma execution_character_set(“utf-8”)
其实网上可以找到不少文章提到还有另一个解决办法, 就是在源码中插入预处理指令#pragma execution_character_set("utf-8")
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
# pragma execution_character_set("utf-8")
#endif
这是关于该指令的官网说明:《execution_character_set》。
根据这个说明,这个指令似乎是VS2015才有的(我的电脑没有别的版本的MSVC所以没办法验证VS2015之前的版本是否支持这个指令),但是在Visual Studio 2015 Update 2
版本就废弃了。我的VS2015版本是Visual Studio 2015 Update 3
,对这个指令确实无效。
Visual Studio 保存UTF-8 without BOM
为什么要用UTF-8 without BOM来保存源码?
主要的原因是linux下编译器不支持UTF-8 with BOM的源码编译,其实如果你的项目没有跨平台编译的要求,并不一定要将源码保存为UTF-8 without BOM格式。
如果你希望在Visual Studio中将源码保存为UTF-8 without BOM格式,如下设置一下高级保存选项
就可以了。
默认是Unicode(UTF-8 带签名)-代码页65001
,这里要修改为Unicode(UTF-8 无签名)-代码页65001
参考文章
《MSVC中C++ UTF8中文编码处理探究》
《/utf-8 (Set Source and Executable character sets to UTF-8)》
《execution_character_set》