C++的跨平台方案(如何解决不带 bom 的 utf8 源文件无法用 vs 编译)

2017-11-02 21:46:59 +08:00
 zhiqiang

之前系统是在 ubuntu 下开发的,整套 gcc/make 工具链已经比较熟悉。

现在有部分功能想在 windows 下编译运行。首先考虑的是用 visual studio,但有个恶心的问题是,visual studio 要求 utf8 必须要有 bom。linux 下的 utf 源代码到 vs 下编译出现一大堆错误。

刚刚尝试了 mingw/gcc,才发现不支持多线程 mutex 之类的。在网上搜了下,说需要安装 w64 版本。但我看 w64 的 gcc 版本只有 4.8.3,而且还不确定有没有别的问题。

不知道大家是怎么弄的,我估计大多数人还是用 vs,这时候该如何处理 bom 的问题?

我想最简单的方法是 git 每次下载文件时自动加上 bom,上传文件时删掉 bom。不知道有没有现成的插件或者配置文件来做这件事情?

4999 次点击
所在节点    C
42 条回复
wangxn
2017-11-03 08:51:18 +08:00
GCC 当然支持编译带 BOM 的文件了,即使默认不行,加个参数就行。
但问题是值不值得加这三个二进制字节到一个纯文本文件中去,譬如 Git 这些都支持不好。
归根到底还是西方话语霸权搞出 UTF-8 这个奇葩来,老老实实用 UCS2 这种(伪)定长编码多好。
ipwx
2017-11-03 08:57:23 +08:00
@wangxn 定长编码天生和 C 语言的 '\0' 终结符相冲,会造成 tons of trouble。
justou
2017-11-03 09:10:10 +08:00
@wwqgtxx 对,我就是用无 BOM 的 utf8, cout 了一行字符串, 因为源文件是 utf-8 no BOM 的, 只有在这种情况下 cl 才会按照源文件编码读入字符串字节, 其它情况下似乎都会按照本地编码读入字符串, 除非字符串字面量用 u8 等修饰符(u8"utf8 编码的字面量", c++11), 我用的 notepad++创建的 3 个文件, 内容都是:

#include <iostream>

int main()
{
std::cout << "VS UTF-8 BOM 问题" << std::endl;
return 0;
}

一个是本地的 cp936 编码, 一个是 utf8 no bom, 另一个 utf8 with bom. 控制台输出分别是:

cp936: VS UTF-8 BOM 问题

utf8 no bom: VS UTF-8 BOM 闂 (cp936 去解码 utf8 编码的字符串, "问题"乱码了)

utf8 with bom: VS UTF-8 BOM 问题 (有 bom 的 utf8 字符串字面量还是按照 cp936 的字节读入的,所以正常)

VS2015 编译没遇到任何错误或警告.

测试工程: 链接: http://pan.baidu.com/s/1slVyEW9 密码:didy
FifiLyu
2017-11-03 09:16:44 +08:00
我多年前遇到一样的问题。我的解决办法是,全部文件都是 BOM+UTF8。仅仅发现在 CentOS5 平台默认 gcc 编译有问题,需要删除 BOM。其它 Linux 发行版都没问题,当然 VS 编译也 OK。

CentOS6/7
Windows XP/2003/7

这些平台用 BOM+UTF8 都没问题。
zhiqiang
2017-11-03 09:25:01 +08:00
@justou 挺奇怪的。含中文 utf8 without bom 在 vs 下 cl 出错,在网上案例很多,我这里也早试过不行。你这个行的话,是不是巧合?

而且我的源代码里,只有注释有中文,代码其实都没有中文的。
zhiqiang
2017-11-03 09:30:44 +08:00
@justou 我刚在你的测试样例上试了下,加入中文注释,会出现 warning,但编译还能成功。

我的工程可能结构比较复杂,编译会直接出错。
enenaaa
2017-11-03 09:33:19 +08:00
@zhiqiang vs 编译不带 BOM 的源码文件。遇到 cp936 不存在的字符才会出问题。 好的话是出警告, 也有因为字符识别错误报错的。
我一般是在中文后面加点换行或英文字符。。
justou
2017-11-03 09:33:36 +08:00
@zhiqiang 试了下, 加了注释中文,也没问题(VS2015 企业版 update3). 因为我想在 VS 里面默认保存 no bom utf8 之前在网上搜索过方案, 也找到了(见 5L), 如果连 VS 都不能支持 no bom 的话, 那个插件几乎没啥用了
forcecharlie
2017-11-03 09:33:48 +08:00
策略一,使用 UTF-8 Without BOM 但不使用中文注释,字符串资源用 RC 文件保存或者其他。

当然如果只是注释中有中文,只要不是 /W4 就不会出问题。

策略二,使用 Visual C++ 2015 or Later 添加参数 /source-charset:utf-8
https://msdn.microsoft.com/en-us/library/mt708819.aspx
https://msdn.microsoft.com/en-us/library/mt708821.aspx
justou
2017-11-03 09:37:39 +08:00
@enenaaa 对, 像这种警告: warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss, 之前使用一些第三方库时遇到过很多
wangxn
2017-11-03 09:49:18 +08:00
@ipwx 这不会造成问题的,C/C++的 wchar_t 就是定长编码。\0 只有在全部字节都是 0 才是有效的,其他情况都是编码的一部分。
ipwx
2017-11-03 10:37:40 +08:00
@wangxn 问题是一堆历史遗留的库呀~ 如果强行推广 UCS-2,可以预见一堆 PHP 的扩展库、一堆 C/C++ 的第三方库,一堆算法库…… 全都挂掉,都要重写。代价太大,所以还是用了 UTF-8 这种 compatible 模式。
wwqgtxx
2017-11-03 11:15:04 +08:00
@zhiqiang mingw-w64 的文档更新的很慢,最新版你要去 sf.net 上下
allenx
2017-11-03 11:26:34 +08:00
utf8 with bom 可能更好点,低版本 vs 不支持不带 bom 的 utf8 格式。
gnaggnoyil
2017-11-03 11:40:19 +08:00
LZ 想要的是不是 git hook?去./.git/hooks 下看看有没有你想要的.
julykitt
2017-11-03 12:07:33 +08:00
安装 git 的时候又让你选 pull 是 Windows,push 是 Unix 的选项啊。你可以试试
zsx
2017-11-03 12:55:57 +08:00
cl /utf-8
owt5008137
2017-11-03 13:09:35 +08:00
1. 写个脚本,全部换成带 BOM
2. WSL
3. 我这里的 Mingw64 里是有 mutex 和线程库的
heliumhgy
2017-11-03 15:23:28 +08:00
msbuild /p:source-charset=utf8 xx.sln
纯记忆手打。。。
iobzo
2017-11-03 17:42:32 +08:00
VS 有插件叫 ForceUTF8 nobom

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/403068

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX