0%

字符集与编码

字符集与编码

字符集:字符集是字符与代码的映射关系,例如 ASCII 字符集的 ‘A’ = 65 = 0x41
编码:将字符集中的代码按一定规则存储于计算机中,例如 ASCII 规定用一字节存储所有 ASCII 字符

编码历史

第一阶段:ASCII 编码

计算机刚开始只支持英语,使用 ASCII 编码,一个字节存储

第二阶段:ANSI 编码,表示其他外文编码

不同国家和地区的 ANSI 编码各不相同
linux 系统查看系统默认编码
locale 的命名规则为<语言>_<地区>.<字符集编码>

1
2
3
4
5
6
7
8
9
10
11
12
[root@1-min huage]# locale  //查看当前系统的语言环境
LC_CTYPE="zh_CN.UTF-8" // 中文linux系统默认UTF-8编码
[root@1-min huage]# locale -a //查看系统支持的所有语言
en_US
en_US.iso88591
en_US.iso885915
en_US.utf8
zh_CN
zh_CN.gb18030 // 2000年3月17日发布,对 GBK 的补充
zh_CN.gb2312 // 1981年5月1日发布,双字节编码
zh_CN.gbk // 1995年12月发布,对 GB2312 补充,双字节编码
zh_CN.utf8

linux 编码转换工具:iconv

1
iconv -f GBK -t UTF-8 file1 -o file2 // 将一个UTF-8 编码的文件转换成GBK编码

windows 系统可通过控制面板更改系统编码,
控制面板” =>“时钟、语言和区域”=>“区域和语言”=>“管理”=>“更改系统区域设置”
或者通过 chcp 命令查看当前代码页,通过 systeminfo 查看 local
System Locale: zh-cn;Chinese (China)

windows 记事本另存为选择编码方式,ANSI 就是系统默认编码,简体中文是 gb2312,繁体中文是 big5 编码

第三阶段:Unicode 编码,万国码

ANSI 编码解决了非英语国家的编码显示问题,但不同国家使用不同编码,相互交流沟通就很麻烦,然后就出现 Unicode 字符集,将世界上所有字符统一编码

Unicode 字符集,规定了世界上所有字符的二进制代码,字符串中存储字符在 Unicode 中的编号

常见 Unicode 字符集的编码方式有 UTF-8,UTF-16,UTF-32 等

文件编码
汉字编码如:gb2312、gbk、gb18030、big5,编码方式决定了字节顺序,跟 cpu 字节序无关,跟大端模式的顺序一致
Unicode 相关编码:
UTF-8,UTF-8 和 gb 系列编码一样,其编码某个汉字产生的字节顺序,由其编码方案决定,不受 CPU 字节序的影响
UTF-16、UTF-32:编码规则要求可以在文件头部的 BOM(Byte Order Mark)来标记字节顺序,FFFE 表示小端,FEFF 表示大端

程序中的编码

c 语言字符串常量有如下形式:
“ s-char-sequence “ (1) 系统默认编码,gcc 为 UTF-8,vs2017 为 gbk
u8 “ s-char-sequence “ (2) (C11 起) UTF-8 字符串字面量
u “ s-char-sequence “ (3) (C11 起) 16 位宽字符串字面量,通常为 UTF-16 编码,有字节序问题
U “ s-char-sequence “ (4) (C11 起) 32 位宽字符串字面量,通常为 UTF-32 编码,有字节序问题
L “ s-char-sequence “ (5) 宽字符串字面量,通常是 Unicode 码点(即 Unicode 顺序编号)

使用 GCC 编译时可以使用如下参数:
-finput-charset 指定源文件(保存文件时选择)的编码方式(若不指定,编译器默认是 UTF-8)
-fexec-charset 指定可执行程序中的字符以什么编码方式来表示,默认是 UTF-8
-fwide-exec-charset 指定可执行程序中的宽字符以什么编码方式来表示,默认是 UTF-8

字符串字面量 (1) 和宽字符串字面量 (5) 的编码是实现定义的。例如, gcc 用命令行选项 -fexec-charset 和 -fwide-exec-charset 选择不同编码

字符串不同的编码到底有什么影响:
如果这个字符串只是程序内部使用,不管什么编码都没有关系
如果这个字符串要输出到控制台或者显示到 GUI 上,那么这个字符串的编码必须和接受方(如控制台)的编码方案一致才可显示,否则乱码

参考:
标准编码百度百科
阮一峰字符编码
c++编码
彻底弄懂 UTF-8、Unicode、宽字符、locale