字符编码小结

前言

i 数字编码

在计算机的世界中,只有0和1,计算机如何能表示无穷无尽的数值呢?人们约定,以8个bit作为一个字节,以4个字节作为一组,用于标识int,这样一来,int就可以表示具有32位0,1组成的二进制数字了,计算机在处理数字的过程中,以每32个bit(4个字节)为一组进行解析,得到一个二进制数字,在需要供人阅读时,在将二进制转换为10进制,这样计算机就能表示我们熟悉的10进制数字了。

这个过程中,我们约定了使用4个字节表示int,在计算机内部就可以每4字节解析一个数字,并且约定计算机内部表示的是2进制数字,计算机展示数字时需要将二进制转换为10进制供人阅读,

这里的两个约定,就是人们在计算机世界中对整数的编码,(当然,真实的整数编码远比这复杂,这里不展开讨论),可以使用四个字节表示数字,自然也就可以使用其他字节数表示数字,这样一来,计算机就可以使用不同的字节数对二进制进行解析,得到不同的数值,而使用几个字节进行解析,就依赖于人们的约定

ii 字符编码

数字可以通过由10进制转换为2进制的方式在计算机内部使用0,1表示,但是字符怎么办呢?遇到新问题的时候,最简单的方法就是将其转换为我们已经解决过得问题,可不可以将其转换为数字呢?毕竟数字其实也是一种符号而已。

在计算机的发明地美国,第一批使用计算机的人约定了一张映射表,将他们使用的字符映射为数字,而数字我们是知道的,可以通过二进制表示,从而在计算机中进行使用。这就是ASCII码,(详细内容后面细说)

这里从字符到数字的映射,其实就是我们所说的字符编码
在这里插入图片描述
图片来自ASCII码对照表

一、字符编码的历史

1.1 第一台计算机

1946年,第一台计算机在美国宾夕法尼亚大学诞生。发明人是美国人莫克利(JohnW.Mauchly)和艾克特(J.PresperEckert),美国国防部用它来进行弹道计算。它是一个庞然大物,用了18000个电子管,占地150平方米,重达30吨,耗电功率约150千瓦,每秒钟可进行5000次运算,这个算力在今天看来也许微不足道,但是在当时却是打开了新的大门。

1.2 ASCII编码

ASCII第一次以规范标准的类型发表是在1967年,当时仅有美国在使用计算机,于是,美国国家标准学会(American National Standard Institute , ANSI) 就搜集了美国所有需要表示的字符,共,为其建立了一张字符编码表,从0-127每个数字映射了一个字符,如此一来,计算机就可以表示美国当时所有的字符了。而因为仅有128个字符,只需要 7个bit即可表示,单计算机的最小储存单位为字节,因此,ASCII使用一个字节表示

  • 0000 0000 ~ 0010 0000 (0 ~ 32 )及127(共33个)是控制字符或通信专用字符(其余为可显示字符),
  • 0011 0000 ~ 0011 1001 (48~57)为0到9十个阿拉伯数字。
  • 0100 0001 ~ 0101 1010 (65 ~ 90)为大写的A-Z字母
  • 0110 0001 ~ 0111 1010 (97 ~ 122)为小写的a-z字母

参考自: 百度百科:ASCII

为什么大小写字母之差刚好是32呢?

Ascii里的大小写代码很简单,只是使用位运算来处理英文字母的大小写转换,因为大小写相差刚刚32,unicode码里面有各种字符之间转换的码表,而ascii转换码表很简单,+-32即可,所以使用0x5f和0x20来做位运算就可以进行转换了,一个小的改进带来的价值有多大。。如果你有几百台机器在做大小写不敏感的字符串匹配和分析,这个改进的价值几何呢?我不清楚,也许google能给个答案。
32,这个数字很凑巧,刚好可以使用位运算来对大小写进行转换,其实是在1963年一次投票后Ascii码中大小写才改进为相差32:

参考自: ASCII码的一段历史

从ascii中,我们已经能隐隐感觉到字符编码中常说的几个术语:

  • 字符:现实世界中的一些符号,表示现实世界中的信息
  • 字符集:现实世界中字符的集合
  • 字符编码:字符映射为数字的映射规则,数字才是最终用于计算机表示的对应字符的格式

1.3 EASCII编码和ISO/IEC 8859编码

计算机逐渐从美国发展到了欧洲,而欧洲国家除了ASCII中的字符外,还有许多其他字符需要表示,这时候ASCII的字符编码已经满足不了需求了,而ASCII编码中仅使用了7个bit,最高位并没有使用,也就意味着若使用上这个第8位,可以表示最多256个字符,于是欧洲国家分别对 ASCII中的 128-255编号进行编码,这就衍生出了EASCII编码

而欧洲各国都使用不同的字符编码,通信起来就较为麻烦,于是衍生出了ISO/IEC 8859-n 编码(n是1-16,12未定义)依据不同的字符集将字符编码分为多个代码页,分别对应与 1-16,这样,各个国家就可以依据需要使用不同的字符编码

参考自: 刨根究底字符编码之四——EASCII及ISO 8859字符编码方案

1.4 GB2312编码,GBK,GB18030, BIG5编码

1.4.1 GB2312

中国汉字太复杂,太多了,当计算机传入中国后,发现仅有一个字节完全不够用,于是中国国家标准总局发布了GB 2312(《信息交换用汉字编码字符集·基本集》),并对该字符集进行了编码,GB 2312 对任意一个字符都采用两个字节表示

  • GB 2312 对任意一个图形字符都采用两个字节表示,并对所收汉字进行了“分区”处理,每区含有 94 个汉字/符号,分别对应第一字节和第二字节。这种表示方式也称为区位码。
  • 01-09 区为特殊符号。
  • 16-55 区为一级汉字,按拼音排序。
  • 56-87 区为二级汉字,按部首/笔画排序。
  • 10-15 区及 88-94 区则未有编码。
  • GB 2312 的编码范围为 2121H-777EH,与 ASCII 有重叠,通行方法是将 GB 码两个字节的最高位置 1 以示区别。

1.4.2 GBK

有部分字符尚未收入GB2312中,而GBK就是GB2312的扩充,与GB2312向下兼容,同样采用双字节进行编码

1.4.3 GB18030

最新一代中文编码字符集,采用多字节变长编码,每个字符由1、2、4个字节编码

1.4.4 BIG5

BIG5是与GB2312同时期的编码格式,GB2312字符集中并没有收录繁体字,而台湾等地是使用繁体字的,因此BIG5应运而生,主要收录了繁体字字符集,并进行编码

参考自: GB2312、GBK、GB18030 这几种字符集的主要区别是什么?

BIG5详细信息可以见 百度百科:大五码

这里,有几个概念需要进行解释:

  • 字符集:这个前面已经说过,是一个字符的集合,如这里的GB2312和BIG5
  • 字符编码:这个前面也说过,是字符映射为数字的一个映射规则,可以理解为一种标准,而这里的GB2312和BIG5都给出了字符的映射规则,因此他们也是字符编码
  • 编码:字符映射为数字的具体方式,可以理解为标准的具体实现方式,ASCII很简单,单字节转为2进制即可,而GB2312和BIG5则复杂一些,给出了每个字节详细的映射规则,
  • 解码:字符编码后,需要依据对应的编码规则对编码后的字节进行解码

1.5 Unicode,UTF16,UTF8

1.5.1 Unicode

计算机世界有了这么多种字符编码标准,而且他们之间大多互不兼容,这样就导致当一个应用需要在多个国家发布时,字符编码成了难题,在本国编码下运行正确的程序,到了其他国家可能就是乱码,为了解决这个难题,国际标准化组织(ISO)一些软件制造商分别开始开发一个统一的字符编码标准,后来,他们发现在做同样的事情,并且也世界上不需要两套不同标准的字符编码,于是他们进行合并,共同开发了Unicode

Unicode characters — A Global Standard to Support ALL the World’s Languages

Unicode是一个用于支持全球语言的统一标准

  • Unicode致力于定制一个足够大的编码表,用以支持全世界的语言系统
  • Unicode为每个字符提供了一个独一无二的编码(码点,也就是一个数字)

Unicode历史版本
在C++中,可以使用 \u\U开头的16进制数字来表示Unicode中的字符,在任意支持Unicode的编译器中,都可以在内部表示对应码点的字符,而具体使用何种编码格式,可以依据计算机使用的编码系统变化
比如

 std::cout << "let them come to \u4E2D\u56FD.\n";

在这里插入图片描述
其中 4E2D和56FD分别是中、国的Unicode码点,要查某个字符的编码可以到这里查询: https://unicode-table.com/en/

《C++ Primer Plus 第6版》
码点:字符编码系统中字符的数字编号,
在Unicode中,Unicode码点通常类似 U+4E2D, U表示这是一个Unicode字符,而4E2D是该字符的16进制编号

关于UnicodeUCS的区别,可以参考这篇文章:unicode和ucs的区别

1.5.2 UTF-16,UTF-8

现在我们知道,Unicode是一种编码标准,它制订了每个字符的码点,但是问题来了,Unicode并没有指定码点如何具体编写为二进制,它不像ASCII和GBK等编码标准,在指定字符码点的同时也制订了每个码点编写为二进制的规则;

UTF-8和UTF-16就是常用的将Unicode的码点编码为具体二进制的编码规则,也就是我们常说的UTF-8编码UTF-16编码

关于UTF-8编码规则,有许多讲的很好的文章,这里我就不多介绍了,有兴趣可以看看一下几篇文章:
阮一峰: 字符编码笔记:ASCII,Unicode 和 UTF-8
知乎问题:Unicode 和 UTF-8 有什么区别?
UTF-16就简单了,简单的讲Unicode码点使用两个字节表示即可,
不过这里面有大端序小端序的问题,后面进行详谈

二、一些常见概念说明

Unicode编码:前面我们知道,Unicode是一个字符集,本身谈不上编码,一般情况下,未指明具体编码为UTF-8和UTF-16时,Unicode编码指的是UTF-16
ANSI编码ANSI本身并不是一种编码格式,但是在记事本中,另存为时,可以选择保存为ANSI格式在这里插入图片描述一般说ANSI编码格式指的是当前系统环境的默认编码格式,比如中国地区的windows系统(安装系统时选择的地区是中国,或者在控制面板->区域中进行设置)默认是GBK编码

运行时编码环境:指的是程序运行时使用那种编码运行,一般取决于运行程序的系统使用的是哪种编码,决定了程序最终展示出来的字符串的字符编码,比如你的系统使用的是 ASCII,但是程序需要显示中文字符,这时候显示的就是乱码了
编译器字符编码:告诉编译器,程序使用的字符编码是那种类型,比如UTF-16,那么编译器会使用UTF-16对程序中的字符进行编码,Visual Studio中有两种:Use Unicode Character Set,Use Multi-Byte Character Set分别指的是UTF-16UTF-8,具体可以查看这里Unicode and Multibyte Character Set (MBCS) Support
代码文本的编码环境:这个很好理解,代码本身是一个文本,这个文本的编码,


以后想到了补充

参考文档:
[1]字符编码的前世今生
[2]百度百科:ASCII
[3]ASCII码的一段历史
[4] 刨根究底字符编码之四——EASCII及ISO 8859字符编码方案
[5] GB2312、GBK、GB18030 这几种字符集的主要区别是什么?
[6] 百度百科:大五码
[7]Unicode characters — A Global Standard to Support ALL the World’s Languages
[8]unicode和ucs的区别
[9]阮一峰: 字符编码笔记:ASCII,Unicode 和 UTF-8
[10]知乎问题:Unicode 和 UTF-8 有什么区别?
[11]Unicode, UTF, ASCII, ANSI format differences

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值