uft-8 BOM 导致编译问题

在windows编译程序时,编译器提示:warning: C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失。并有大量的不合理错误提示。

而当前源文件确实已经是utf-8编码了,此时有可能是因为编译器解析源文件出现问题。

将源文件使用记事本或者其它文本编辑器保存成带BOM的utf-8就可以正常识别。

uft-8 BOM 导致编译问题_第1张图片

(带BOM,图中红色)

uft-8 BOM 导致编译问题_第2张图片

(不带BOM)

 

相关背景知识:

编译器在编译过程中,处理字符串时会涉及下面两种字符集:

源码字符集(the source character set):源码文件是使用何种编码保存的。
执行字符集(the execution character set):可执行程序内保存的是何种编码。

要想使程序不会乱码,必须满足:
1) 编译器准确识别了源码字符集,从而得到正确的字符串数据。
2) 运行环境的编码与执行字符集相同。运行环境的编码可通过setlocale函数来配置,“setlocale(LC_ALL, "")”表示使用系统默认编码。对于简体中文Windows来说一般是GB2312,如果执行字符集相同,那就能正常显示,否则会乱码。

 以VC2010为例,
源码字符集:如果源文件有签名(BOM)字符,就按它的编码来解析;否则使用本地Locale字符集。
执行字符集:对于char类型,如果有“#pragma execution_character_set”,就按它的编码来存储字符串;否则使用本地Locale字符集。对于wchar_t类型,总是使用UTF-16编码。

BOM是什么

Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。在UCS 编码中有一个叫做 "Zero Width No-Break Space",中文译名作“零宽无间断间隔”的字符,它的编码是 FEFF。而 FFFE 在 UCS 中是不存在的字符,所以不应该出现在实际传输中。UCS 规范建议我们在传输字节流前,先传输字符 "Zero Width No-Break Space"。这样如果接收者收到 FEFF,就表明这个字节流是 Big-Endian 的;如果收到FFFE,就表明这个字节流是 Little- Endian 的。因此字符 "Zero Width No-Break Space" (“零宽无间断间隔”)又被称作 BOM(即Byte Order Mark)。

UTF-8以字节为编码单元因此不需要 BOM 来表明字节顺序,但可以用 BOM 来表明编码方式。接收者收到以开头的字节流,就知道是 UTF-8编码或者UTF16BE,UTF16LE.

FE FF            UTF16BE
FF FE            UTF16LE
EF BB BF      UTF8


 

你可能感兴趣的:(Qt,c++,visual,studio)