Windows下c++字符编码(一)

字符编码基础

在谈c++之前,不得不先来说说各种字符编码。我们知道最早的英文字符采用ascii,因为英文字符很少,因此一个char就够用了。但是由于处理其他语言的需求,8位的char显然不够用,这就要求更多位数的编码。

GBK和ANSI

在中国,我们的国标是GBK,(准确的说经历了GB2312->GBK->GB18030的发展过程),我们常说的汉字占两个字节也就是来源于此。

微软作为一个世界大厂,采用什么编码呢?微软虽然在语言支持上很上心,不过编码却很混乱,微软的默认编码是ANSI,这是个什么东西呢?这其实就是大杂烩,英文还是ascii,中文是GBK,港澳台使用它们那边的Big5……等等。这些编码并不统一,是非常没有兼容性的。其实ANSI不是一种编码,不过我就这么简单的说了,关于ANSI具体是什么,你可以看看这篇文章:https://www.cnblogs.com/malecrab/p/5300486.html

由于我们主要还是说中文问题,以下提到ANSI的地方,你应该立即联想到,中文是采用GBK编码的。其中,值得一提的是GBK编码是双字节的,这是中文字符占两个字节说法的由来。

Unicode

由于各地编码的不统一,于是产生了Unicode,Unicode其实是一个标准,而不是一种编码。Unicode现有两套标准,ucs2和ucs4,一开始认为双字节够用,就是ucs2,后来发现双字节不够用,那就扩展到4字节吧,于是就有了ucs4。Unicode现在主要有三种实现方式。即utf-8,utf-16,和utf-32。

utf-16

先讲utf-16,这是采用双字节表示的,遵从ucs2。在存储时,按两个字节的排布顺序,可以分为UTF-16LE(Little Endian,小端字节序)和UTF-16BE(Big Endian,大端字节序),微软所说的Unicode默认就是 UTF-16LE。注意微软后来也搞了Unicode,但是微软自己鼓吹的Unicode只是其中一种实现方式而已。

utf-16后来发现双字节不够用,于是增加了采用一对双字节来表示一个字符,这其中也包括一些生僻汉字,之后我们将会提到具体例子。所以其实标准的utf-16也是变字长的编码,很多人认为utf-16编码是定长编码,这其实是错误的。此外,utf-16不等价于ucs2,可以认为ucs2是定长编码(双字节),而utf-16是ucs2的扩展。

utf-32

再说utf-32,既然双字节不够用,那就用四字节吧,于是就有了ucs4标准和utf-32实现方式。utf-32所有的字符都采用4个字节,这才是真正的定长编码。utf-32等价于ucs4,utf-32也存在存储顺序的问题。由于utf-32基本没人用,就不详细展开。

不过,我们知道代码源文件还是ascii字符主导。而在网页上,大量的标记都是ascii字符。utf-32要用4字节,utf-16也要2字节,都比最初的ascii长,这显然是非常浪费空间的,更何况网络传输数据越少越好,因此utf-16和utf-32都是不合用的。

utf-8

utf-8解决了这个问题,utf-8是完全的变长编码,兼容ascii,也就是ascii编码部分保留,其他的字符根据情况有2,3,4字节。其中特别值得注意的是汉字一般是三个字节,也有四个字节的生僻字情况。(如果你拥护utf-8的话,请不要在说汉字占2字节这样的傻话了。)

utf-8是Unix/Linux系统的默认编码,在这些系统上使用charstring,无论输入输出都是使用utf-8,因此一般不必担心编码问题。在这些系统上,string = "你好世界"size()是12,也就是一个字符三个字节,是没有任何问题的。你编辑c++源代码基本不必担心编码问题。

但是在windows下就很复杂了。windows自带Notepad是默认ANSI编码的。Notepad++和VS Code是默认utf-8编码,未经配置的gvim以及visual studio默认也是ANSI。关于c++源代码写中文的注意事项,将在之后的文章中详细说明。

总结

现在我们来总结一下编码我们提到的编码知识:

  • Unicode是编码规范而不是编码方式,它有两个标准,主要有三种实现方式。

  • utf-8和utf-16都是变长编码,只有utf-32是定长编码。

  • 网页上基本采用utf-8作为编码方式,utf-32基本很难用到。

  • 微软系统采用的ANSI默认编码,兼容ascii,其中文采用GBK编码,汉字为双字节,兼容性不好。

  • 微软也有Unicode,它使用的Unicode是utf-16,不兼容ascii,中文为双字节,少数为4字节。

  • Unix/Linux采用utf-8变长编码,兼容ascii,其中中文一般为3字节,少数4字节。

建议

现在我们来讨论c++的字符编码问题。

在Unix/Linux系统下,我建议一律采用utf-8编码,一般没有任何问题。不过值得注意的一点是此系统下,wchat_twstring表示的字符是4字节的字符,应该就是utf-32了。然而utf-32除了定长这一特点之外,没有任何好处,太浪费空间,用处很少,没必要去碰它。不过wstring的问题我们之后还会讨论,你将会了解更多。

在Windows下,如果你不得不在源文件写中文,而且又不想看我之后几篇又臭又长的详解,你可以使用Qt专有的QString,或者使用Visual Studio来写代码。前者的的默认编码是utf-16,如果不用生僻字,甚至可以按照定长编码的方式处理字符。后者是依靠微软这个IDE强大的功能,可以处理各种编码的源文件。

如果你还想了解更多工作原理,请看之后的文章。我将会首先使用g++8.1.0做实验,说明c++的字符串的一些特性。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值