目录

前言

一、什么是编码,数据类型和编码有什么关系?

二、英文字符编码

ASCII编码

三、中文编码

1. GB2312标准

2. GBK编码

3. 其他中文编码

四、Unicode字符集

1. UTF-32

2. UTF-16

2. UTF-8

3. BOM

五、ANSI编码


前言

我们在开发中是不是经常会遇到这样的问题,比如你在VS2019中创建了一个工程,里面有C语言程序和中文注释,有一天,根据工作需要,你要把其中的一部分C文件和H文件移植到Keil工程中,当你通过复制黏贴把相应文件移植到Keil工程中,并使用MDK打开时,却发现,你移植的文件C语言程序是正常显示的,但是中文却成了一堆乱码,并且一编译各种莫名其妙的报错。这其实就有可能是你的VS2019和Keil使用了不同的编码方式,因为大部分编码兼容ASCII编码,而C语言程序是英文字符,采用了ASCII编码,所以正常显示,而中文编码就不同了,比如内存中同样的0xB0A1,使用不同编码标准去对0xB0A1解码,得到的可能就是不同的汉字。

在计算机世界中,只有0、1两种数字,不论是英文、中文还是数字,在计算机中都是以01的形式存储的。因此,要想把文字存储到计算机上,就要规定特定的01序列来表示文字。编码就是规定特定的01序列来表示文字的过程,编码表示了字符在计算机中的存储形式。


一、什么是编码,数据类型和编码有什么关系?

我们在计算机中经常见到的文字、数字、英文字母、图片、视频、音频等,这些信息在计算机中都是以二进制的形式存储的,因为内存条是电子元器件组成的,它们只有高电平低电平两种状态,即0和1两个值。实际上,我们所说的十进制、八进制等进制以及char、int、float等数据类型这些概念都是对于程序员而言的,比如十进制、十六进制只是一个数字对我们的表现形式不同,逢十进一或逢十六进一的区别;而数据类型,int、char、unsigned int等等,这些数据类型是对内存的解释不同,数据类型说明了这段内存所能表示的数据范围不同,比如char占一个字节,表示的数据范围是0~255,int是4字节,unsigned int表示无符号4字节数据。有时候在程序中我们会对变量进行类型转换,比如十进制转十六进制,又或者是char型转int型,这些转型都是对内存的解释(主要是内存的大小,数据的范围),比如char b,那么b占一个字节,我们让b=1,然后转型(int)b,其实b还是1,只不过它现在被解释为占据4个字节的内存。总之,上面这些情况,不管如何转换,同一个数据不会因为类型转换而改变内存中的实际数据,b在char类型时是00000001,转为int型后成了00000000000000000000000000000001,它还是那个1,不管是十六进制0x01还是十进制1,它在内存中都是上面的二进制。这是因为数据类型只是对内存的解释,而真正决定它们在计算机中的存储形式(是0001序列还是1110序列)的是编码,编码是指一个数据在计算机中的01序列是如何存储的。

数据类型是固定大小内存块的别名,它说明了这块内存所能表示的数据大小范围;

字符集(character set)定义了文字和二进制的对应关系,并给每个文字分配一个一对一的唯一编号;

字符编码(character Encoding)规定了文字的编号是怎么在计算机中存储的。

二、英文字符编码

ASCII编码

用8位二进制进行编码,用于表示控制字符、英文字符、数字字符。因为使用8位二进制编码,所以ASCII编码只能表示256个字符,编号范围为0~255。常用的ASCII码如下:

表示字符 十六进制形式 十进制形式
0~9 0x30~0x39 48~57
A~Z 0x41~0x5A 65~90
a~z 0x61~0x7A 97~122

不管是ASCII码的十六进制形式还是ASCII码的十进制形式,它都是一种解释性的概念,对内存数据的一种解释形式,用于表达给程序员看的概念,它们在计算机中的存储都是同样的二进制数,不会因为进制改变而改变。这种使用8位二进制来表示或存储字符的过程就叫做编码(一串二进制01和一个字符一一对应的过程)。这些用ASCII码表示的字符的集合叫做ASCII字符集。

在英文世界中,使用26个字母就可以拼写出全部的英文单词,每个字字母就是一个字符,所以,用8位的ASCII码就可以对整个英文世界进行编码。

三、中文编码

英文编码可以用字母编码来代替,这是因为所有英文单词都可以拆分成26个英文字母的组合。而中文就不一样了,中文一个字就是一个整体,只能按照一个字来编码,中文汉字成千上万,如果仅用8位ASCII码来编码,那么是明显不够的,ASCII码顶多表示256个汉字,所以就有了下面这些中文编码方式。

1. GB2312标准

GB2312总共覆盖了6763个常用汉字,GB2312标准把ASCII码表127号之后的扩展字符集去掉,并规定,小于127(0x7F)的编码按照ASCII标准进行解码,当出现连续两个大于127(0x7F)的编码时,这两个连续的大于0x7F的编码表示一个汉字,第一二个字节都是用0xA1~0xFE进行编码。其中,ASCII码中原有的数字字符、英文字符、标点等称为半角字符,大于0x7F的相应字符编码称为全角字符。

GB2312解码规则:当使用GB2312编码标准时,给定一串字符编码,按照字节进行检测,首先检测每个字节的大小,如果字节值小于0x7F,就用ASCII标准解码,如果连续两个字节的值都大于0x7F,就把这两个字节视为一个整体,使用GB2312标准解码。

举例:

0x61 0xB0 0xA1 0x61

从第一个字节开始检测,0x61小于0x7F,用ASCII标准解码,它表示英文字符“a”,第二个字节0xB0大于0x7F,第三个字节0xA1大于0x7F,连续两个字节大于0x7F,把它们连为一体使用GB2312解码为中文字符“啊”,第四个字节0x61小于0x7F,用ASCII标准解码,它表示英文字符“a”。综上,可解码如下

0x61 0xB0 0xA1 0x61
a a

2. GBK编码

GBK编码在GB2312的基础上又增加了14240个汉字、生僻字和符号。按照GB2312的编码方式,两个字节已经不够用了,这时,GBK编码制定了新的标准:只要出现一个大于0x7F的字节,那么这个字节和它后面一个字节共两个字节就表示一个汉字(GB2312规定两个字节都大于0x7F才表示一个汉字),这样做的好处就是,GBK编码兼容了ASCII编码和GB2312编码。

GBK解码规则:当使用GB2312编码标准时,给定一串字符编码,按照字节进行检测,首先检测每个字节的大小,如果字节值小于0x7F,就用ASCII标准解码,如果遇到一个大于0x7F的字节,就把该字节和它后面一个字节连在一起用GBK标准进行解码,然后从第三个字节开始继续遍历检测。

举例:

0x61 0xB0 0x56 0x62

从第一个字节开始检测,0x61小于0x7F,用ASCII标准解码,它表示英文字符“a”,第二个字节0xB0大于0x7F,那么就把0xB0、0x56连在一起用GBK标准解码,然后从0x62开始继续检测,解码后如下

0x61 0xB0 0x56 0x62
a 癡(chi) b

3. 其他中文编码

GB18030编码:使用4字节编码,兼容ASCII、GB2312、GBK。包括2000年编制的GB18030-2000,2005年编制的GB18030-2005。

Big5编码:多用于台湾香港等地,主要是收录了繁体字。在包含汉字数量上来说,Big5是GBK的子集,但是二者的编码方式是不同的,比如同样“啊”,GBK编码为0xB0A1,Big5编码为0xB0DA。

四、Unicode字符集

每个国家和地区都有一套自己的文字,不同的文字系统就要使用不同的编码标准,这就出现这样一个问题,同一个二进制编码在不同的编码标准中可能代表了不同的字符,比如0xB0A1,在GBK编码标准中为“啊”,而在Big5编码标准中就不是这个字了。这样,各个编码标准之间的不兼容就导致使用起来非常不方便。国际标准化组织ISO,将全球所有的语言所使用的字母、符号、文字进行统一编号,每个字符指定唯一一个标号与之对应(ASCII码编号不变),字符的编号从0x000000~0x10FFFF,该编号集称为Universal Multiple-Octet coded Character Set,简称UCS,一般也叫做Unicode。Unicode字符集仅仅是对所有字符进行了编号,并没有指定这些编号的编码规则,所以,后来才出现了各种Unicode的编码规则Unicode Transformation Format,典型的Unicode编码规则如UTF-8,UTF-16,UTF-32等。

1. UTF-32

Unicode Transformation Format 32,用32位(4字节)对Unicode字符集进行编码。编码时,Unicode字符集中的每一个字符都用4字节表示,直接把字符对应的Unicode编号转换为二进制数进行存储。而正因为UTF-32用4字节为每个字符编码,所以,UTF-32不兼容ASCII编码,使用ASCII编码标准写的程序,通过UTF-32编码方式打开会显示乱码。

解码时,直接按四个字节检测,编码与Unicode标号一一对应。

字符:A ASCII编码:0x41 Unicode编号:0x0000 0041 UTF-32编码:0x0000 0041
字符:啊 GBK编码:0xB0A1 Unicode编号:0x0000 554A UTF-32编码:0x0000 554A

2. UTF-16

Unicode Transformation Format 16,用16位(2字节)或32位(4字节)对Unicode字符集进行编码。对Unicode字符编号在0~65535的字符使用2字节编码,将每个字符的编号直接转换为2字节的二进制数0x0000~0xFFFF。而Unicode字符集在0xD800~0xDBFF区间内的编号不表示任何字符,UTF-16用这段编号与Unicode字符集中大于0xFFFF的字符编号进行映射,得到扩展的4字节编码。UTF-16也不兼容ASCII编码。

UTF-16解码时,按两个字节去检测,如果这两个字节都不在0xD800~0xDFFF之间,就说明是双字节编码的字符,使用双字节解码;如果这两个字节在0xD800~0xDFFF之间,说明是4字节编码的字符,以4字节解码。

2. UTF-8

Unicode Transformation Format 8,用1,2,3,4个字节对Unicode字符集进行编码,每个字符根据自己的编号范围进行相应编码。它的编码规则是这样的:

对于UTF-8单字节的编码,该字节最高位设为0,剩余位填入字符的Unicode编号,对于Unicode编号在0x00000000~0x0000007F的字符,UTF-8编码只要一个字节,兼容ASCII编码。对于N字节的编码,第一字节最高位开始,前N位置为1,第N+1位设0,剩余字节最高位设为10,这N个字节的其余空位填充该字符的Unicode编号,高位补0。具体可见下表:

Unicode编号 UTF-8编码
第1字节 第2字节 第3字节 第4字节
0x00000000~0x0000007F 0xxx xxxx
0x00000080~0x000007FF 110x xxxx 10xx xxxx
0x00000800~0x0000FFF 1110xxxx 10xx xxxx 10xx xxxx
0x00010000~0x0010FFFF 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx

解码时,看第一个字节

0开头:单字节解码;

110开头:双字节解码;

1110开头:三字节解码;

11110开头:四字节解码;

UTF-8编码的时候,汉字一般是占三个字节的。

3. BOM

Byte Order Mark,我们在Notepad++中的Encoding选项中可以看到诸如Encoding in UTF-8,以及Encoding in UTF-8-BOM这样的选项,带不带标签不会影响对字符的编码解码,假如把不带标签的UTF-8编码转换为带标签的UTF-8-BOM编码,程序和中文注释都不会出现乱码,但是这两种是有区别的。比如我们常用的emWin,在emWin中文支持中,它只支持不带标签的UTF-8编码,如果使用带标签的UTF-8-BOM,虽然不会报错,但是在控件中,无法显示这些中文。

五、ANSI编码

ANSI编码是Windows中的一种称呼,像GBK、GB2312都是ANSI编码,在不同语言的操作系统中,ANSI表示的编码是不同的,比如中文、泰文、法文都有各自的编码方式,这些编码方式对ASCII编码的扩展就是ANSI。

【字符编码详解】ASCII、GB2312、GBK、UTF-8、UTF-16编码与Unicode字符集相关推荐

  1. 计算机编程种常见的几种编码详解

    计算机编程种常见的几种编码详解 其实计算机编程离不开编码 但是大多数都不能真正全面了解各种编码 今天就来好好和几位编码熟悉熟悉 一.字符.字符集和字符编码方式 字符:字符是抽象的最小文本单位.它没有固 ...

  2. x.509数字证书编码详解

    转自:http://blog.sina.com.cn/s/blog_49b531af0102eahs.html x.509数字证书编码详解 一. X.509数字证书的编码 X.509证书的结构是用AS ...

  3. 字符编码详解及由来(UNICODE,UTF-8,GBK)

    字符编码详解及由来(UNICODE,UTF-8,GBK) 各种字符编码方式详解及由来(ANSI,UNICODE,UTF-8,GB2312,GBK) - 2009-01-29 09:53     一直对 ...

  4. Python2.7字符编码详解

    Python2.7字符编码详解 目录 Python2.7字符编码详解 声明 一. 字符编码基础 1.1 抽象字符清单(ACR) 1.2 已编码字符集(CCS) 1.3 字符编码格式(CEF) 1.3. ...

  5. 转1:Python字符编码详解

    Python27字符编码详解 声明 一 字符编码基础 1 抽象字符清单ACR 2 已编码字符集CCS 3 字符编码格式CEF 31 ASCII初创 311 ASCII 312 EASCII 32 MB ...

  6. 可能是最详细的字符编码详解

    Created By JishuBao on 2019-04-02 12:38:22 Recently revised in 2019-04-03 12:38:22   欢迎大家来到技术宝的掘金世界, ...

  7. 字符编码详解及利用C++ STL string遍历中文字符串

    作者:非妃是公主 专栏:<笔记><C++> 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成.--曾国藩 文 ...

  8. Python字符编码详解

    Python字符编码详解 转自http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html Python字符编码详解 本文简单介绍了各种常用的 ...

  9. 嵌入式汉字显示原理及GBK编码详解

    嵌入式汉字显示原理及GBK编码详解 ~~~~~~~~        关于各个编码的介绍和转换可以看我的另一篇博客:[C语言实现]十六进制面值转字符串.字符面值转十六进制.UNICODE与GBK互转,U ...

最新文章

  1. 计算机系统结构总概,计算机系统结构概论
  2. AfxInitExtensionModule和AfxTermExtensionModule
  3. VSFTP服务--Linux学习笔记
  4. Linux 命令之 ll -- 列出当前文件或目录的详细信息
  5. linux yum下载不安装,【APP】yum只下载软件不安装的两种方法
  6. 基于LSTM的时间序列预测-原理-python代码详解
  7. [RK3288][Android6.0] 如何配置MIPI DSI Clock和PCLK
  8. sysdig_Linux 监控和调试利器 Sysdig 入门教程
  9. JavaSE详细教程.1
  10. QT学习之做一个简易图片处理器(后续补全)
  11. Excel2013函数公式大全(一)
  12. 河南省第十届ACM程序设计大赛参赛心得
  13. Android 10.0 webview版本升级的方法
  14. win7防火墙开启ping
  15. 使用ffmpeg把mp4与m3u8相互转换的操作
  16. TVbox带会员带推广版本
  17. windows下使用nvcc和nvprof
  18. document.forms[0].submit();和document.forms[0].action = ““;问题
  19. ansible一些基本操作
  20. 犹太人:赚钱能培养孩子独立责任奋进多种能力!

热门文章

  1. GitHub自学系列之二「加入 GitHub」
  2. 接口和抽象类区别以及应用场景
  3. 胡学纲数据结构c语言PDF,辽宁工程技术大学综合训练项目任务书一(数据结构)
  4. 蓝的成长记——追逐DBA(13):协调硬件厂商,六个故事:所见所感的“服务器、存储、交换机......”
  5. Vue项目更丝滑的几个小技巧
  6. 使用Moses进行英文分词tokenizer、truecasing、lowercasing、clean等
  7. 投资共享充电宝项目市场分析报告
  8. 汽车UDS诊断详解及Vector相关工具链使用说明——2.3.7 读取所有支持的DTC(0x19 0A)
  9. Oracle中用exp/imp命令快速导入导出数据
  10. 条件随机场(CRF)详解