常量

常量(Constant)是程序中最基本的元素,有字符常量(Character Constant)、数字常量和枚举常量。枚举常量以后再介绍,现在我们看看如何使用字符常量和数字常量:

printf("character: %c\ninteger: %d\nfloating point: %f\n", '}', 34, 3.14);

字符常量要用单引号括起来,例如上面的'}',注意单引号只能括一个字符而不能像双引号那样括一串字符,字符常量也可以是一个转义序列,例如'\n',这时虽然单引号括了两个字符,但实际上只表示一个字符。和字符串字面值中使用转义序列有一点区别,如果在字符常量中要表示双引号"和问号?,既可以使用转义序列\"和\?,也可以直接用字符"和?,而要表示'和\则必须使用转义序列。[4]

计算机中整数和小数的内部表示方式不同,因而在C语言中是两种不同的类型,例如上例的343.14,小数在计算机术语中称为浮点数(Floating Point)。这个语句的输出结果和Hello world不太一样,字符串"character: %c\ninteger: %d\nfloating point: %f\n"并不是按原样打印输出的,而是输出成这样:

character: }
integer: 34
floating point: 3.14

printf中的这个字符串称为格式化字符串(Format String),它规定了后面几个数据以何种格式插入到这个字符串中,%号(Percent Sign)后面加个字母c、d、f在printf中分别解释成字符型、整型和浮点型的转换说明(Conversion Specification),分别用后面的三个常量来替换它们,也就是说它们只是在格式化字符串中占个位置,并不出现在最终的打印结果中,这种用法通常叫做占位符(Placeholder)。这也是一种字面意思与真实意思不同的情况,但是和转义序列又有区别:转义序列是编译器在处理字符串字面值时转义的,而占位符是由printf解释的,格式化字符串实际包含的字符是character: %c换行integer: %d换行floating point: %f换行,其中的%c仍然是字符串中的两个普通字符,而当字符串传给printf处理时,printf却不把它当成是普通字符,而是解释成占位符。事实上前面例子中的"Hello, world.\n"也是格式化字符串,只不过其中不包含占位符。

有时候不同类型的数据很容易弄混,例如"5"、'5'、5,如果你注意了Delimiter就会很清楚,第一个是字符串,第二个是字符,第三个是整数,看了下文你很快就会知道为什么一定要严格区分它们之间的差别了。

习题

1、总结前面介绍的转义序列的规律,想想在printf的格式化字符串中怎么表示一个%字符?写个小程序试验一下。



[4] 读者可能会奇怪,为什么需要规定一个转义序列\?呢?因为C语言规定了一些三连符(Trigraph),在某些特殊的终端上缺少某些字符,需要用Trigraph输入,例如??=表示#。Trigraph极不常用,介绍这个只是为了让读者理解C语言规定转义序列的作用,即特殊字符转普通字符,普通字符转特殊字符,\?属于前者。极不常用的C语法在本书中通常不会介绍。