Visual Studio UTF-8编码中文注释导致的罕见问题

Windows、Linux、Mac平台下的纯文本文件,在内容仅为英文字母以及其他ASCII编码能表达的字符的情况下,文本一律为ASCII编码。

当然内容包含中文等非ASCII字符时,Windows下默认使用ISO 8859-1编码,而Linux和Mac平台则默认使用UTF-8编码。

ISO编码的文件在Linux和Mac平台下是乱码,而UTF-8在Windows下可以正常识别。但是Visual Studio有可能会出问题!!

VS的编译器对Unicode源代码支持如下:
1. UTF-16 little endian with or without byte order mark (BOM)
2. UTF-16 big endian with or without BOM
3. UTF-8 with BOM

使用Windows下的Visual Studio编译器建议使用ASCII编码,但是如果代码是跨平台的,难免会把Linux平台下的UTF-8编码的文件放到Windows下使用。

这种情况下一般VS会给予如下warning:

warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失

这时候如果出现以中文结尾的一行注释,那么这个换行符很可能会被丢掉,导致下一行代码被注释(并不是一定会出错,估计是和对应字符的编码值有关,这个概率还是很高的。在文本中间插入或删除字符很容易改变这种性质,因此就会出现“改了行注释代码就执行错了”的诡异bug或者“改了下注释代码就执行对了”的诡异“解决方案”)。有时候会出现如下编译错误:

error C2447: “{”: 缺少函数标题(是否是老式的形式表?)

这是因为你的函数名那一行上面的中文注释导致函数名那一行被编译器认为是注释了,如下:

// 中文注释
void func()  // 这一行被当作是注释了
{
    do_something...
}

而这种bug并不是所有情况下都会在编译时被发现,能在编译是发现的bug都是好bug。比如如下代码就坑多了:

// 中文注释
if(xxx)  // 这一行被当作是注释了
{
    do_something...
}

对于如上的代码,可能就会由于编码的原因导致if(xxx)部分被当作注释,而本来是满足if条件才执行的do_something就变成了一律执行,这种错误很难被发现。

所以跨平台传输代码最好使用git的自动转码功能(Windows平台的git安装的时候的默认选项就是这样的)。

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注

12 + 4 =