字符编码的由来
一开始由欧美人发明的ASCII编码表,一个字节表示一个符号,并且仅用低7位。但是后面普及后各个国家语言的差异性无法继线引用ASCII的编码表进行表示众多符号。
各国家开始引入各自的编码表,我国有GB2312编码表、内地人使用GBK来表示汉字、港澳台用BIG5来表示,用两个字节表示一个汉字,但是这又引入另外一个问题就是各个地区的编码格式均不同,导致不能通用。
后面引入了unicode编码表,它用0-0x10FFFF来表示一个符号,即全世界通用的编码表,根据码值来获取对应符号,但是我们可以看出如果存储每个字符均直接以码值来存储,那么一个字符就需要3个字节大小(0x10.FF.FF),导致大量浪费空间,而且对应欧美人来说用ASCII码甚至能节省2/3的空间!然后又引入了3中存储方式:
- UTF-8: 可变长编码
- UTF-16LE:固定两字节存储,小端编码格式(低字节位于高位)
- UFT-16BE:固定两字节存储,大端编码格式(高字节位于高位)
- 各编码格式详细可以参数文章:https://www.cnblogs.com/z-sm/p/4688994.html
编码区别
UTF-8:用1-4个字节来表示一个符号,对于单字节,第一位为0,后面7位位unicode码,因此对于存储英文的空间与ASCII相同;对于n字节,第一个字节的前n位都为1,第n+1位为0,后面字节的前两位一律都设为10,剩下的未提及的二进制位,全为该符号的Unicode码。
UTF-16LE/UTF-16BE:对于小端,前面两字节为FF,FE表示,对于大端则用FE,FF表示。后面的每两个字节表示一个字符,即固定16位表示一个unicode码。
可以看出:对于UTF-8,在英文较多时比较节省空间,而且容错性比较高,即使丢了一个字节的数据,也只会影响该字节的显示,对后面不造成影响,而其他两种则丢失一个字节会造成后面全部乱码。
符号如何显示
每个编写文件的平台都会有对应字体文件,该字体文件含编码表、字体数据。指定某个字体时,他将数据全部以该字体对应的编码表码字进行存储。
编译不同格式文件
gcc编译时,一般编译出的文件默认解析与表示的编码格式为utf-8
即 gcc -o main main.c //默认为utf-8
可以通过指定不同格式来进行编译(man gcc搜charset):
- -finput-charset = xxx 表示以什么格式解析文件
- -fexec-charset = xxx 表示可执行程序里的字符以什么编码方式表示
实列:gcc -finput-charset=GBK -fexec-charset=UTF-8 main main.c
以GBK国标进行解析,指定可执行文件以UTF-8编码来存储表示。