vs2015:/utf-8选项解决UTF-8 without BOM 源码中文输出乱码问题

时间:2022-02-04 10:44:41

本来我已经参考网上关于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)》

vs2015:/utf-8选项解决UTF-8 without BOM 源码中文输出乱码问题

vs2015:/utf-8选项解决UTF-8 without BOM 源码中文输出乱码问题

#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格式,如下设置一下高级保存选项就可以了。
vs2015:/utf-8选项解决UTF-8 without BOM 源码中文输出乱码问题

默认是Unicode(UTF-8 带签名)-代码页65001,这里要修改为Unicode(UTF-8 无签名)-代码页65001
vs2015:/utf-8选项解决UTF-8 without BOM 源码中文输出乱码问题

参考文章

《MSVC中C++ UTF8中文编码处理探究》
《/utf-8 (Set Source and Executable character sets to UTF-8)》
《execution_character_set》