神奇的 utf8

 前两天写了个CS的小东西,里面会有一些中文字符串传来传去的,结果就发生了神奇的事情。

 

代码中有这么简单的一句

<code>

  const char* szWelcome = "你好啊";

</code>

 

结果输出到console是乱码! 于是查了下,发现所有的源代码中所有的中文都自动编码为UTF8格式了。

 

晕,还能这么聪明? 好在UTF8也不赖,UTF8就UTF8吧。于是重新设计了下规划,检查了下整个流程,在内部全按UTF8格式的字符串处理了,在输出的时候统一加上了utf8 => gb2312 的转换。

 

效果还不错,于是继续往下走。逐渐又添加了些东西。结构逐渐丰富起来的时候,出现神奇的事情,中文又变成乱码了!又是一通测试,最终确定服务器上的所有中文,这回不在被编译为utf8格式了,而是gb2312格式!

 

查来查去,几乎都要以为以前的编译器自动编译为UTF8是个错觉。可是把代码回溯到过去,编译出来就是UTF8的字符串,更新到最新,就是GB2312的字符串! 最神奇的是,服务器是GB2312,可是客户端一直是UTF8! 两个通讯的时候,就是两个格式并存的,你怎么解码都只有一半正确!

 

为了这个编码问题,头都快炸了。都曾想过干脆直接用unicode的整个环境得了。还好就是在整改unicode的时候,没花多长时间就发现用到的一个第三方开源库并不支持unicode环境,于是及早放弃,回到了灵异事件上来。

 

......

 

中间的一大堆查错测试的苦差经历就不提了,直接说灵异事件的结果。

 

vc express 2008 环境下, 假设demo.cpp 包含字符串如  "中文测试",那么:

 

1.  如果demo.cpp是带BOM的UTF8格式,那么编译器能够识别utf8源代码,并将utf8源代码中的字符串转换为本地编码,也就是gb2312格式;

 

2.  如果demo.cpp不是utf8格式,那么编译器也能够识别,并且无需转换,字符串本身就是gb2312格式的。

 

3.  如果demo.cpp是不带BOM的UTF8格式,那么编译器就犯傻了, 他就会按照普通ansi格式处理。也就是他认为文件里面的字符串已经是gb2312编码了,他不做变换直接使用。 于是错巧错着,字符串就是UTF8的格式了。

 

 

但是后来为什么又编译不出来UTF8格式了呢? 因为 3 这种情况,毕竟是编译器犯傻造成的。 犯傻这种事,也不是每次都这么歪打正着刚刚好的,是不是。

一般来说,对于3这种无BOM的UTF8格式源代码,编译器是按照普通的ansi格式处理的。里面没中文也罢,有中文的话他会发现有点不对劲,于是报一个 C4819 的警告。一般这样子也能蒙混过关。 问题是他认错了格式,难免就会出些偶尔的意外。 我的服务器就是这种情况:

 

其中一段中文,因为测试,这么写的,碰巧碰上了枪口。

<code> const char* p = "的啦"; </code>

 

然后编译器就发神经了,他会报告这一行包含非法的换行符(错误C2001)。

 

我一开始还信以为真,瞪大了眼睛,来来回回反反复复三番五次几次三番逐字逐句掘地三尺的检查,也没查出哪有换行符来。 上面写的字符串很短,实际上是我为了示例精简的。我代码里那一句话很长,很长很长。我一个字一个字的删除一回编译一回才找出原因,那个时候我还有蛮后悔自己写代码为什么这么罗嗦的。

 

原因就是: “的”这个中文,不能打头。他前面一定得有个中文,连英文(如“me的书”)都不行。否则就触到编译器的某根神经了。

 

解决办法也行很简单,说话换个方式,又或者直接把源文件保存为带BOM的UTF8格式。

 

很不幸的是当时我不巧选择了后面的一种方法,然后就出现了一开始说的灵异现象......

 

 

 

 

 PS:

  这里的gb2312, ansi 只是相对utf8来说明问题的。严格来说不是很准确。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值