行者无疆 始于足下 - 行走,思考,在路上

gcc: converting to execution character set

跨平台的软件开发总会遇到各种各样的问题,尤其是在一个山寨小公司里面,更是无法避免,因为程序最开始就没有考虑跨平台的事情……

废话少说,话说前两天在编译程序的时候遇到一个诡异的问题,如题目所说,gcc报错说"cannot convert to execution character set",字面意思应该是有关字符集的问题。借助baidu,找到了freebsdchina的一个帖子,大概的解释是:

"C/C++中有这样两个编码概念:

  • source character set:源文件的编码
  • execution character set:执行环境的编码

还有一些额外的环境变量就是locale类的LC_XXX

在编译的时候,要执行从source character set到execution character set的转换。这个是由编译器来完成的。locale是在程序的运行时决定程序的行为。

由于Freebsd下gcc的局限,你要使用wide characters,就是L"xxxx"这样的,源文件的编码必须为UTF-8。如果要在shell下正确的看到std::wcout输出的文字,则你的shell的locale也必须为UTF-8。另外,如果你使用的是gnome-terminal,注意它的显示编码也必须是utf-8

如果你采用了UTF-8的方式保存文件,"xxx" 这样的字符串在你的程序中就是以utf-8的方式保存的, L"xxx"这样的字符串在你的程序中就是以UCS-4的方式保存的。

为了永远摆脱乱码的困扰,我建议大家忍一忍,都使用UTF-8的方式保存文件吧。"

我忽然想起来,在我的iOS工程中,所有的源代码文件都是从原先的Windows Mobile工程引入的,自然所有的源文件编码都是GBK系列的(至于GBK、GB2312以及GB18030之间有哪些微妙的关系,我也懒得搞清楚了),而VMware里面的Mac系统编码是Unicode,所以可能会出现这个问题。不过为了确认,我又回到自己的Linux系统下,在UTF-8的终端下编译了一个GBK编码的c语言文件,结果也可以顺利执行,看来这可能与gcc的版本有关。我的ArchLinux下的gcc是4.6版本,而Mac OS X下的gcc似乎还停留在3.x版本。

至于字符编码的转换,在Linux下的基础工具和函数库都是iconv,但是iconv比较原始,无法自动检测文件的编码,需要显式指定,enca基于iconv,但是提供了根据语言自动检测文件编码的功能,并且更加健壮,更适合于脚本批处理。我用下面的命令将所有的源文件编码转换成UTF-8:

find . -name \*.c -o -name \*.h -o -name \*.cpp | xargs enca -L zh_CN -x UTF-8

至于Unicode,UTF-8,GB18030,ISO-8859,ASCII等,除了ASCII,我一个都没有彻底搞明白。罢了罢了,还是期待Unicode早点“一统江湖,千秋万载”吧。




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee