为神马不要在代码里写中文(一)

c++中的字符串是个很麻烦的东西,有了宽字符之后变得更加麻烦,据说c++0x要引入raw string,就是类似这种

const char* str = R"噼里

回个车

啪啦";

的奔放写法,所以未来估计会更加的乱。最近看了一些关于字符串编码的东西,才明白双引号之间的这些玩意儿还是有很多说道的,接下来详细记录一下,要是说错了,那就日后发现再改= =b

双引号搞出来的这种字符串称为string literal,相当于一个const char*或者const wchar_t*。vc的编译器(估计大部分都有)有个优化,叫string pool,是说编译的时候所有相同的字符串会被合并,只保留一份在内存中,因此相同的string literal会返回相同的指针。

但是只要有字符就会牵扯到字符编码,因为程序只存取byte,写在引号之间的字符对应哪些byte呢?另外,代码文件本身就是一个文本文件,也存在编码的问题,这二者之间的关系又是如何呢?请不要走开,我们广告之后再进行讨论……

跨平台移植刻不容缓……程序中惊现神秘字串……究竟是程序员脑残还是编译器脑残……答案即将揭晓,请看走进科学之《不要在代码中写中文》……

嗯嗯,广告完毕,答案是~~~~~~这得看用的什么编译器了╮(╯_╰)╭

我写了段程序,用于打印string literal的各个byte:

#include <iostream>
using namespace std;

void outbyte(const void* buf, int len)
{
	unsigned char* p = (unsigned char*)buf;
	cout<<"Len:"<<len<<endl;
	while(len--)
	{
		cout<<hex<<(int)(*p++)<<" ";
	}
	cout<<endl;
}

int main(int argc, char** argv)
{
	const char* p = "a好人";
	outbyte(p, sizeof("a好人"));

	const wchar_t* pw = L"a好人";
	outbyte(pw, sizeof(L"a好人"));

	return 0;
}

代码分别保存成不同的编码格式,有utf-8, 以BOM(byte order mark)开头的utf-8,还有gbk。然后用gcc4,vc6,vc2003,vc2005以及vc2008编译并运行,得到了很有趣(蛋疼?)的结果。

嗯嗯,结果和分析就明天再贴了= =b

One thought on “为神马不要在代码里写中文(一)”

  1. F的几个明天都过了。。第二篇还没来。
    快写第二篇啊,别玩tiny wings了

Leave a Reply

Your email address will not be published. Required fields are marked *