字符集与编码
字符集:字符集是字符与代码的映射关系,例如 ASCII 字符集的 ‘A’ = 65 = 0x41
编码:将字符集中的代码按一定规则存储于计算机中,例如 ASCII 规定用一字节存储所有 ASCII 字符
编码历史
第一阶段:ASCII 编码
计算机刚开始只支持英语,使用 ASCII 编码,一个字节存储
第二阶段:ANSI 编码,表示其他外文编码
不同国家和地区的 ANSI 编码各不相同
linux 系统查看系统默认编码
locale 的命名规则为<语言>_<地区>.<字符集编码>
1 | [root@1-min huage]# locale //查看当前系统的语言环境 |
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 上,那么这个字符串的编码必须和接受方(如控制台)的编码方案一致才可显示,否则乱码