在C/C++语言中,
在对源文件作预处理的时候,有两条基本原则:
一、凡是以//开头的为单行注释
二、凡是以\结尾的表明此行还没有结束
因而预处理器在处理的时候会先按第二条规则,看每行的末尾的那个 字符是否是”\”,是的话,就下一行接到本行。而后把全部 以//开头的注释和 /* */的块注释去掉。
可是存在一个问题,入下:
对于big5中的汉字而言,其第一个字节的编码范围是0xA1 - 0xFE,第二个字节是0x40 - 0xFE。而’\'的ASCII码是0x5c,这就意味着:凡是以big5编码的文件,若是gcc没有正确的认为它的 源文件的编码是big5,那么就可能出现由于 单行注释末尾是汉字,而把下行的代码吃掉的状况。这样是很危险的,可是gcc会给出一个警告:”warning: multi-line comment In file”。这样的问题在gbk中一样存在。
将下面的代码php
// 你好\ int main(int argc, char* argv[]) { return 0; }
以gbk的方式保存,并采用gcc 3.4编译。
不管是solaris 8仍是freebsd 6.2,不管shell的locale的设置是 zh_CN.GBK仍是 zh_CN.UTF-8,所获得的错误都是相同的。
$ gcc -c testgbk.cpp
testgbk.cpp:5: error: expected unqualified-id before “return”
testgbk.cpp:6: error: expected declaration before ‘}’ token
g++ 3.3下显示:
shell
testgbk.cpp:3: error: parse error before `return’ide
截图以下:测试
缘由很简单,我把“好”字的GBK编码的后 半个 (?)字节改为了’\'的编码,从而获得了”篭”字。
gcc发现’\'后面接着的就是’\n’,故而把下一行”int main(int argc, char* argv[])”也当作注释一并删除掉了。按gcc 3.4的man页,gcc会根据shell的locale设置来 猜想 源文件的编码格式,不然它会把其看成utf-8来处理。可是据我在Freebsd和solaris系统中的观察,gcc 3.4并无根据 环境变量来猜想源文件的编码。
编码
一个不错的解决方案是:强行给gcc添加-finput-charset=big5这样的参数,来解决此问题。相似的还有-fexec-charset,-fwide-exec-charset用于指定执行环境的编码。可是不幸的是,gcc内部的处理都是基于utf-8的,且其转换工做通常是靠系统的iconv转码库来完成的。 因此系统库必须提供 GBK<-> UTF-8 、BIG5 <-> UTF-8 的编码。spa
例如,我在Freebsd 6.2下使用这样的参数编译一个测试文件:
$ gcc -c testbig5.cpp -finput-charset=big5 -fexec-charset=big5 -fwide-exec-charset=big5
所获得的输出是:
cc1plus: no iconv implementation, cannot convert from big5 to UTF-8
cc1plus: no iconv implementation, cannot convert from UTF-8 to big5
cc1plus: no iconv implementation, cannot convert from UTF-8 to big5
因此这种方案的缺点是:
一、缺少通用性,缺少可移植性。
Freebsd的内核中的转码是靠查一个16位的表,因此没法处理utf-8中的汉字(由于汉字是3字节),而直到最新的,要到08才能发布的Freebsd 7.x,此问题也依然没有被解决。而Solaris最初的代码是基于BSD的。它所提供的iconv转码功能也很是差。
二、添加了不少额外的转码操做。
目前,utf-8(unicode)还没有彻底容纳GBK、big5的所有字符。不少字符是转换不过去的。
另外一个折衷的方案是:保证每行注释都以句号或者空格结尾。
缺点是,须要检查并改动不少文件。并且,特殊汉字依然有可能出如今源文件的常量字符串中。问题依旧。
例如:
const char* s=”你篭”;
写成这样的怪样子就能够编译了:
const char* s=”你篭”";
较好的解决方案是源文件都以UTF-8格式编码。这样能够最大限度的减小转码次数。最完全的解决方案是引入gettext,不在源文件中存储汉字的常量字符串。改用单独的文件存储。目前包括不少php论坛、blog都已采用这种方案。可是这样作原本是为了支持英、法、汉多语言,解决翻译的问题。若是单为了简、繁的问题就这么作,代价太大。翻译