char ios
可被应用于全部8bit以及8bit如下的字符集,例如: US-ASCII,ISO-Latin-1和ISO-Latin-9以及UTF-8.程序员
char16_tweb
可被用于UCS-2,也可被用于UTF-16的code unit(代码单元).算法
char32_t编程
可被用于UCS-4/UTF-32.网络
wchar_tide
它一般等价于char16_t或者char32_t.函数
US-ASCII编码
7-bit字符集,于1963年完成标准化,用于电传打字机和其余设备,最开始的16个字符是不可打印的。spa
ISO-Latin-1或ISO-8859-1
这是一个8bit的字符集,于1987年完成标准提供西欧语言的全部字符,这个字符集也是下面全部字符集的基础.
UCS-2
这是一个16bit的定长字符集(2byte),提供Universal Character Set(全球字符集)和Unicode(统一码)中最重要的65536个字符.
UTF-8
这是个multi-byte字符集,使用1-4个8bit值,用来表现Universal Character Set(全球字符集)和Unicode(统一码)的全部字符.主要被普遍的应用于万维网(world wide web).
UTF-16
这也是一个multi-byte字符集,使用1-2 code unit(每一个16bit),用来表现Universal Character Set(全球字符集)和Unicode(赞成码)之全部标准化字符.
UCS-4或UTF-32
这个32bit的定长字符集(4byte),提供Unversal Character Set(全球字符集)和Unicode(统一码)之全部标准化字符.
多字节和宽字符文本:
1,在多字节(Multibyte)表示法中,字符所用的byte是变更的。一个1-byte字符(例如 ISO-Latin-1字符)后面再跟1个,2个或者3个byte,例如中文或者日文。
2,宽字符(wide-character)表示法,字符所用的byte数目固定,与其所表示的字符无关,典型的byte个数是2个或者4个.
在咱们了解Unicode以前首先了解一下GB,GBK等待国产字符集.
做者:Tuxify
连接:https://www.zhihu.com/question/19677619/answer/12616362
1, GB2312-80
GB 2312 或 GB 2312-80 是中国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,又称GB0,由中国国家标准总局发布,1981年5月1日实施。GB2312编码通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎全部的中文系统和国际化的软件都支持GB 2312。
GB 2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。
GB2312对任意一个图形字符都采用两个字节表示,并对所收汉字进行了“分区”处理,每区含有94个汉字/符号,分别对应第一字节和第二字节。这种表示方式也称为区位码。
10-15区及88-94区则未有编码。
GB2312的编码范围为2121H-777EH,与ASCII有重叠,通行方法是将GB码两个字节的最高位置1以示区别。
2 ,GBK
GBK即汉字内码扩展规范,K为汉语拼音 Kuo Zhan(扩展)中“扩”字的声母。英文全称Chinese Internal Code Specification。
GBK共收入21886个汉字和图形符号,包括:
GBK向下与GB2312 彻底兼容,向上支持ISO 10646国际标准,在前者向后者过渡过程当中起到的承上启下的做用。
GBK 采用双字节表示,整体编码范围为8140-FEFE之间,首字节在81-FE之间,尾字节在40-FE之间,剔除XX7F一条线。GBK编码区分三部分:
GBK/2:0xB0A1-F7FE, 收录GB2312汉字6763个,按原序排列;
GBK/3:0x8140-A0FE,收录CJK汉字6080个;
GBK/4:0xAA40-FEA0,收录CJK汉字和增补的汉字8160个。
GBK/1:0xA1A1-A9FE,除GB2312的符号外,还增补了其它符号
GBK/5:0xA840-A9AO,扩除非汉字区。
GBK区域中的空白区,用户能够本身定义字符。
3 ,GB18030
GB 18030,全称:国家标准GB 18030-2005《信息技术中文编码字符集》,是中华人民共和国现时最新的内码字集,是GB 18030-2000《信息技术信息交换用汉字编码字符集基本集的扩充》的修订版。
GB 18030与GB 2312-1980彻底兼容,与GBK基本兼容,支持GB 13000及Unicode的所有统一汉字,共收录汉字70244个。
GB18030 编码是一二四字节变长编码。
ASCII,GB(K),Unicode的区别与联系:
连接:https://www.zhihu.com/question/19677619/answer/27516663
好久好久之前,有一群人,他们决定用8个能够开合的晶体管来组合成不一样的状态,以表示世界上的万物。他们看到8个开关状态是好的,因而他们把这称为”字节“。再后来,他们又作了一些能够处理这些字节的机器,机器开动了,能够用字节来组合出不少状态,状态开始变来变去。他们看到这样是好的,因而它们就这机器称为”计算机“。
开始计算机只在美国用。八位的字节一共能够组合出256(2的8次方)种不一样的状态。 他们把其中的编号从0开始的32种状态分别规定了特殊的用途,一但终端、打印机赶上约定好的这些字节被传过来时,就要作一些约定的动做。赶上0×10, 终端就换行,赶上0×07, 终端就向人们嘟嘟叫,例好赶上0x1b, 打印机就打印反白的字,或者终端就用彩色显示字母。他们看到这样很好,因而就把这些0×20如下的字节状态称为”控制码”。他们又把全部的空 格、标点符号、数字、大小写字母分别用连续的字节状态表示,一直编到了第127号,这样计算机就能够用不一样字节来存储英语的文字了。你们看到这样,都感受 很好,因而你们都把这个方案叫作ANSI 的”Ascii”编码(American Standard Code for Information Interchange,美国信息互换标准代码)。当时世界上全部的计算机都用一样的ASCII方案来保存英文文字。
后来,就像建造巴比伦塔同样,世界各地的都开始使用计算机,可是不少国家用的不是英文,他们的字母里有许可能是ASCII里没有的,为了能够在计算机保存他们的文字,他们决定采用 127号以后的空位来表示这些新的字母、符号,还加入了不少画表格时须要用下到的横线、竖线、交叉等形状,一直把序号编到了最后一个状态255。从128 到255这一页的字符集被称”扩展字符集“。今后以后,贪婪的人类再没有新的状态能够用了,美帝国主义可能没有想到还有第三世界国家的人们也但愿能够用到计算机吧!
等中国人们获得计算机时,已经没有能够利用的字节状态来表示汉字,何况有6000多个经常使用汉字须要保存呢。可是这难不倒智慧的中国人民,咱们不客气地把那些127号以后的奇异符号们直接取消掉, 规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一块儿时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样咱们就能够组合出大约7000多个简体汉字了。在这些编码里,咱们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里原本就有的数字、标点、字母都通通从新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127号如下的那些就叫”半角”字符了。 中国人民看到这样很不错,因而就把这种汉字方案叫作 “GB2312“。GB2312 是对 ASCII 的中文扩展。
可是中国的汉字太多了,咱们很快就就发现有许多人的人名没有办法在这里打出来,特别是某些很会麻烦别人的国家领导人。因而咱们不得不继续把 GB2312 没有用到的码位找出来老实不客气地用上。 后来仍是不够用,因而干脆再也不要求低字节必定是127号以后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,无论后面跟的是否是扩展字符集里的内容。结果扩展以后的编码方案被称为 GBK 标准,GBK包括了GB2312 的全部内容,同时又增长了近20000个新的汉字(包括繁体字)和符号。 后来少数民族也要用电脑了,因而咱们再扩展,又加了几千个新的少数民族的字,GBK扩成了 GB18030。今后以后,中华民族的文化就能够在计算机时代中传承了。 中国的程序员们看到这一系列汉字编码的标准是好的,因而通称他们叫作 “DBCS“(Double Byte Charecter Set 双字节字符集)。在DBCS系列标准里,最大的特色是两字节长的汉字字符和一字节长的英文字符并存于同一套编码方案里,所以他们写的程序为了支持中文处理,必需要注意字串里的每个字节的值,若是这个值是大于127的,那么就认为一个双字节字符集里的字符出现了。那时候凡是受过加持,会编程的计算机僧侣 们都要天天念下面这个咒语数百遍: “一个汉字算两个英文字符!一个汉字算两个英文字符……”
由于当时各个国家都像中国这样搞出一套本身的编码标准,结果互相之间谁也不懂谁的编码,谁也不支持别人的编码,连大陆和台湾这样只相隔了150海里,使用着同一种语言的兄弟地区,也分别采用了不一样的 DBCS 编码方案——当时的中国人想让电脑显示汉字,就必须装上一个”汉字系统”,专门用来处理汉字的显示、输入的问题,可是那个台湾的愚昧封建人士写的算命程序就必须加装另外一套支持 BIG5 编码的什么”倚天汉字系统”才能够用,装错了字符系统,显示就会乱了套!这怎么办?并且世界民族之林中还有那些一时用不上电脑的穷苦人民,他们的文字又怎么办? 真是计算机的巴比伦塔命题啊!
正在这时,大天使加百列及时出现了——一个叫 ISO (国际标谁化组织)的国际组织决定着手解决这个问题。他们采用的方法很简单:废了全部的地区性编码方案,从新搞一个包括了地球上全部文化、全部字母和符号 的编码!他们打算叫它”Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “unicode“。
unicode开始制订时,计算机的存储器容量极大地发展了,空间不再成为问题了。因而 ISO 就直接规定必须用两个字节,也就是16位来统一表示全部的字符,对于ASCII里的那些“半角”字符,unicode包持其原编码不变,只是将其长度由原来的8位扩展为16位,而其余文化和语言的字符则所有从新统一编码。因为”半角”英文符号只须要用到低8位,因此其高8位永远是0,所以这种大气的方案在保存英文文本时会多浪费一倍的空间。
这时候,从旧社会里走过来的程序员开始发现一个奇怪的现象:他们的strlen函数靠不住了,一个汉字再也不是至关于两个字符了,而是一个!是的,从unicode开始,不管是半角的英文字母,仍是全角的汉字,它们都是统一的”一个字符“!同时,也都是统一的”两个字节“,请注意”字符”和”字节”两个术语的不一样,“字节”是一个8位的物理存贮单元,而“字符”则是一个文化相关的符号。在unicode中,一个字符就是两个字节。一个汉字算两个英文字符的时代已经快过去了。
unicode一样也不完美,这里就有两个的问题,一个是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,咱们已经知道,英文字母只用一个字节表示就够了,若是unicode统一规定,每一个符号用三个或四个字节表示,那么每一个英文字母前都必然有二到三个字节是0,这对于存储空间来讲是极大的浪费,文本文件的大小会所以大出二三倍,这是难以接受的。
unicode在很长一段时间内没法推广,直到互联网的出现,为解决unicode如何在网络上传输的问题,因而面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF-8就是每次8个位传输数据,而UTF-16就是每次16个位。UTF-8就是在互联网上使用最广的一种unicode的实现方式,这是为传输而设计的编码,并使编码无国界,这样就能够显示全世界上全部文化的字符了。
UTF-8最大的一个特色,就是它是一种变长的编码方式。它可使用1~4个字节表示一个符号,根据不一样的符号而变化字节长度,当字符在ASCII码的范围时,就用一个字节表示,保留了ASCII字符一个字节的编码作为它的一部分,注意的是unicode一个中文字符占2个字节,而UTF-8一个中文字符占3个字节)。从unicode到uft-8并非直接的对应,而是要过一些算法和规则来转换。
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
—————————————————————–
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Notice: 不管是UTF-8,UTF-16,仍是UTF-32,亦或者是UCS-2,UCS-4都是属于Unicode.
Unicode和多字节(Multi-byte):
计算机中的字符并非保存为图像,每一个字符都是经过一个编码来表示,而每一个字符究竟使用哪一个编码表示,取决于所使用的字符集(charset)。
在最初的时候世界上只有一种字符集-ASCII字符集,它使用7bits表示一个字符,总共能够表示128个字符,以后又进行扩展使用8bits表示一个字符,总共能够表示256个字符。
到了后来计算机再各个国家开始被应用ASCII显然不能知足其余国家需求。因而各个国家在ASCII标准上制定本身的字符集,这些从ASCII标准上派生出来的字符集一般被称为ASCII字符集,他们的正式名字应该是MBCS(Multi-byte-character-system)。这些派生字符集的特色是他们使用大于128的作为一个Leading byte,和紧跟在Leading byte后面的第二个(甚至第三个)byte共同组成一个世纪的字符编码.好比咱们国家的GB-2312.
例如在GB-2312字符集中,“连通”的编码为C1 AC CD A8,其中C1和CD就是Leading Byte。前127个编码为标准ASCII保留;
例如’0‘的编码是30H(30H表示十六进制的30)。软件在读取时,若是看到30H,知道它小于128就是标准ASCII,表示“0”,看到C1大于128就知道它后面还有另外的编码,所以C1 AC一同构成一个整个的编码,在GB-2312字符集中表示“连”。
因为每种语言都制定了本身的字符集,致使最后存在的各类字符集实在太多,在国际交流中要常常转换字符集很是不便。所以,提出了Unicode字符集,它固定使用16 bits(两个字节、一个字)来表示一个字符,共能够表示65536个字符。将世界上几乎全部语言的经常使用字符收录其中,方便了信息交流。标准的Unicode称为UTF-16。后来为了双字节的Unicode可以在现存的处理单字节的系统上正确传输,出现了UTF-8,使用相似MBCS的方式对Unicode进行编码。注意UTF-8是编码,它属于Unicode字符集。Unicode字符集有多种编码形式,而ASCII只有一种,大多数MBCS(包括GB-2312)也只有一种。Unicode的最初目标,是用1个16位的编码来为超过65000字符提供映射。但这还不够,它不能覆盖所有历史上的文字,也不能解决传输的问题 (implantation head-ache's),尤为在那些基于网络的应用中。已有的软件必须作大量的工做来处理16位的数据。
所以,Unicode用一些基本的保留字符制定了三套编码方式它们分别是UTF-8,UTF-16和UTF-32。正如名字所示,在UTF-8中,字符是以8位序列来编码的,用一个或几个字节(byte)来表示一个字符。这种方式的最大好处是:UTF-8保留了ASCII字符的编码作为它的一部分。例如,在UTF-8和ASCII中,‘A'的编码都是0x41。 UTF-16和UTF-32分别是Unicode的16位和32位编码方式。考虑到最初的目的,一般说的Unicode就是指UTF-16。
Notice: 对于UTF-16和UTF-32会在完整的字符序列一开始放一个byte order mark(BOM),用于标示它使用的是big-endian(此为默认)仍是little-endian.
Big-endian和Little-endian:
Big endian和Little endian是CPU处理多字节数的不一样方式。例如“汉”字的Unicode编码是6C 49。那么写到文件里时,到底是将6C写在前面,仍是将49写在前面?若是将6C写在前面,就是Big endian。仍是将49写在前面,就是Little endian。
“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开仍是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另外一个丢了王位.
当一个软件打开一个文档的时候首先要肯定该文档所用的字符集是什么,下面的这种插入字符集标识的方法称为BOM:
1,若是是UTF-8会在文档的开头插入一个不显示的字符:EF BB BF
2,若是是UTF-16/UCS-2(Big-endian)会在文档的开头插入一个不可见的字符:FE FF
若是是UTF-16/UCS-2(Little-endian)会在文档的开头插入一个不可见的字符:FF FE
3,若是是UTF-32/UCS-4(Big-endian)会在文档的开头插入一个不可见的字符:FE FF 00 00
若是是UTF-32/UCS-4(Little-endian)会在文档的开头插入一个不可见的字符:00 00 FF FE
4,若是是GB,GBK是不会插入任何标志所以程序只能靠蒙.
<-----------------------------------我是分割线---------------------------------------->
咱们已经了解了这么多编码了下面开始程序相关了:
在C/C++中咱们必须明确两个概念:
源码字符集(The source character set) | 源码文件是使用哪一种字符集保存的 |
执行字符集(The excution character set) | 执行程序时候内存中的字符编码 |
源文件字符集如何设置? | 正如前面介绍的经过在文件开头插入一个标志 |
执行字符集如何设置? | C++是经过设置std::locale |
注意若是是MSVS2015若是源文件字符集被使用utf那么程序的执行字符集也被默认使用utf8!
不须要再手动设置std::locale了.
也就是说:
//source.cpp Notice:该cpp文件已经被用utf-8(BOM)的方式保存. #include <iostream> int main() { std::basic_string<char> str("十花"); //这两个字符串实际上是一致的.不管用不用u8标识. std::basic_string<char> str(u8"十花"); return 0; }