[生活常识] 汉字在 UTF-8 里是怎么编码的?
luanyanjia · · 科技·工程
今天我突然想到,既然 char 只能储存
我们随便输出一个字看看是什么情况。
freopen("1.out","w",stdout);
std::string s="神";
std::cout<<s;
打开 1.out,发现文件的编码是这样的:
E7 A5 9E
看来汉字是通过多个字节合成的。但是这引入了另一个问题:我从小到大学的都是存汉字要两个字节,到这里怎么变成三个了呢?这和 UTF-8 编码的存储有关系。
UTF-8 中,每个字符都用两个字节去存储,在纯使用 ASCII 字符的时候会显得比较浪费,因为使用了两倍的空间。
所以 UTF 就搞出了一种方案,让 ASCII 里的字符还是一个字节存储,但是这样计算机就不知道怎么分割了,所以 UTF 规定对于更长的字符,如果要占用
对于字符 é(U+00E9),其编码就是
对于字符 神(U+795E),其编码就是
对于字符 𝄞(U+1D11E),其编码就是
黑色的就是字符原来的编码。
这就是 UTF 中存储字符的方式了,现在我打算干一些神秘的东西,如果把格式故意改错,记事本里会显示什么呢?
freopen("1.out","w",stdout);
std::string s;s.resize(8);
s[0]=0xE6,s[1]=0x88,s[2]=0x91;
s[3]=0xE7,s[4]=0x88,s[5]=0xB1;
s[6]=0xE4,s[7]=0xBD;//s[8]=0xA0;
std::cout<<s;
输出:
鎴戠埍浣
看得出来我们一开始想输出 我爱你,但是删掉最后一个之后变成了乱码,这是什么原理呢?其实是记事本发现 UTF-8 格式不对,就使用 GBK 之类严格两个字节表示一个汉字的编码来直接解析了。如果你在终端中中文输出乱码,也是这个原理,只需要统一你终端和 IDE 的编码格式就可以了。