
1.15 字符

视频讲解
在C语言中,使用char来声明字符变量,printf函数使用%c来输出字符。其实字符变量还可以用来存放整数,并且会输出意想不到的结果,这又是怎么一回事呢?来看下面这个例子:

程序实现如下:

这里声明了一个字符变量a,并用它存放一个大写字母'C'。然后调用printf函数,将变量a使用%c字符的形式以及%d整数的形式打印出来。于是结果为C=67。
这不由让我们想到了莫尔斯密码,字符也同样是利用“查表”的原理。C语言中有一张对照表,将二进制数与英文字符一一对应,这就是ASCII字符表。
标准ASCII字符表使用7位二进制数来表示所有的大写和小写字母,数字0~9,标点符号,以及在美式英语中使用的特殊控制字符。其中,ASCII字符表上的数字0~31以及127(共33个)分配给了控制字符,用于控制打印机等一些外围设备,见表1-4。
表1-4 ASCII字符表(1)

数值32~126分配给了能在键盘上找到的字符,见表1-5。
表1-5 ASCII字符表(2)

正如上面的例子中的大写字母'C',如果直接将它存放在字符变量中的数值打印出来,就是ASCII字符表'C'对应的数值,即67。下面例子声明几个字符变量,先给它们直接赋值整数,再以字符的形式打印:

程序实现如下:

不难得出结论:字符类型事实上就是一个特殊的整型,所以字符类型也有取值范围,也可以用signed和unsigned修饰。对于整数类型来说,如果不写signed或unsigned,那么默认是signed带符号位的。但是,C标准并没有规定char必须是signed char还是unsigned char, C语言将这个决定的权力交由编译系统自行实现。不要小看这个细节,很多程序员用C语言写出来的代码含有隐含的漏洞,就是由于没有重视这些小细节导致的。
比如,开发一个程序,需要用一个变量来存放用户的身高数据。某程序员使用char类型来存储身高的数据,在他的编译系统里,char默认是unsigned char,取值范围也就是0~255。但是同样的代码,如果放到本书搭建的环境上,结果又是怎样的呢?

程序实现如下:

天哪,小甲鱼都逆向生长,长到地底下去了……
所以,这个例子给我们的经验就是:写任何代码,都不要想当然。