我们都知道计算机内部是使用二进制保存所有的信息。二进制只有0和1,那么计算机中的文本又是怎么保存的呢?
二进制可以表示数字,我们可以事先约定好,给每个数字对应一个字母,这样就可以用数字来表示字符。现代系统中最常用的的字符编码标准就是ASCII标准。
ASCII
ASCII主要是用一个单字节大小的整数表示一个字符。ASCII一共有128个字符,编码见下图:
查上表可以知道,字符空格”SPACE”是32(二进制00100000),大写的字母A是65(二进制01000001)。所有ASCII码都只需要七位二进制,最高一位为0 。
helloworld.c的文本表示
上节我们用到的helloworld.c文件就是以字节序列的方式存储在文件中。每个字节都是一个整数值,也对应了相应的字符。我们可以用十六进制编辑器打开之前的文本文件,可以对照ASCII表查看
像这种只由字符构成的文件叫做文本文件,其余的文件叫做二进制文件。
char
c语言中的char类型用于储存字符。字符都是用整数编码的,所以char类型实质保存的是整数。c标准规定char的大小是一个字节,这也使指向char的指针可以按照字节的单位寻址,在一些底层操作中也会用到。
在ASCII系统中,char类型就是使用ASCII编码的;对于其他的字符编码系统,则不同于ASCII。以后讨论的char都是使用ASCII编码的。
char的符号取决于实现
char的大小是一个字节,它表示的整数范围却有两种情况。这是因为c标准并没有指出char是有符号还是无符号的,在不同的系统环境中,char有可能是signed char(有符号,范围-128 – 127)也有可能是unsigned char(无符号,范围0-255)。ASCII码的范围是0-127,因此不管是有符号还是无符号都可以表示全部的ASCII码。
单引号
c语言中单引号表示一个字符,它的值就是该字符对应的编码。
char c = ‘A’;
在使用ASCII的系统中,’A’ 的值就是65 。这和
char c = 65;
是一样的。不过第二种写法只能用于ASCII系统,而且可读性差,所以不推荐。
转义字符
有些常见的ASCII非打印字符,键盘上没有对应的按键,所以c语言中定义了转义字符,使用反斜杠+其他字符表示。
‘\n’表示换行符,它的值是十进制10 。
总结:单引号的值是引号内的字符对应的编码值。
其他字符编码
英语用ASCII的128个字符表示就足够了,可是对于其他语言就不一定了。例如汉语就有成千上万的汉字,肯定不能用1个字节。简体中文常见的编码方式是GB2312,使用两个字节表示一个汉字,共收录6763个汉字。
不同的语言使用自己的编码,如果交流的两方编码不一致,就会出现乱码。所以,人们考虑使用一种编码表示世界上所有的字符,所以出现了Unicode(又叫统一码、万国码、单一码)。Unicode给世界上每一个符号都给予一个独一无二的编码,但是没有规定储存方式。(但是Unicode和GB2312编码并不一致)
一个字节肯定不能表示所有字符,如果规定n个字节表示一个字符,那么英文部分只需要1个字节就能表示,多余的字节就会浪费。于是出现了
utf-8
UTF-8是Unicode的实现方式之一,它是一种变长的编码。它的规则有:
1. 对于ASCII码使用一个字节表示,和ASCII码一致。
2. n字节的符号(n>1),第一个字节的前n位都为1,第n+1位为0,后面每个字节的前两位一律设为10。剩下的没有设置的二进制位,填入这个符号的unicode码。
utf-8的编码如下:
1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
ANSI
用记事本保存的时候有ANSI选项。这种方式对于英文文件是ASCII编码,对于简体中文文件是GB2312编码,对繁体中文版会采用Big5码)。