3.6.5 常量

在旧版本(标准前)的C中,如果想建立一个常量,必须使用预处理器:

3.6.5 常量 - 图1

无论在何地使用PI,都会被预处理器用值3.14159代替(在C和C++中都可以使用这个方法)。

当使用预处理器创建常量时,我们在编译器的范围之外能控制这些常量。对名字PI上不进行类型检查,也不能得到PI的地址(所以不能向PI传递一个指针和一个引用)。PI不能是用户定义的类型变量。PI的意义是从定义它的地方持续到文件结束的地方;预处理器并不识别作用域。

C++引入了命名常量的概念,命名常量就像变量一样,只是它的值不能改变。修饰符const告诉编译器这个名字表示常量。不管是内部的还是用户定义的数据类型都可以定义为const。如果定义了某对象为常量,然后试图修改它,编译器将会产生错误。

必须用下述方式说明一个常量类型:

3.6.5 常量 - 图2

在标准C和C++中,可以在参数列表中使用命名常量,即使列表中的参数是指针或引用(也就是说,可以获得const的地址)。const就像正常的变量一样有作用域,所以可以在函数中“隐藏”一个const,确保名字不会影响程序的其余部分。

const由C++采用,并加进标准C中,尽管它们很不一样。在C中,编译器对待const如同变量一样,只不过带有一个特殊的标记,意思是“不要改变我”。当在C中定义const时,编译器为它创建存储空间,所以如果在两个不同的文件中(或在头文件中)定义多个同名的const,连接器将生成发生冲突的错误消息。在C中使用const和在C++中使用const是完全不一样的(简而言之,在C++中使用得更好)。

3.6.5.1 常量值

在C++中,一个const必须有初始值(在C中不是这样)。内建类型的常量值可以表示为十进制、八进制、十六进制、浮点数(不幸的是,二进制数被认为是不重要的)或字符。

如果没有其他的线索,编译器会认为常量值是十进制。数值47、0和1101都被认为是十进制数。

常量值前带0被认为是八进制数(基数为8)。基数为8的数值只能含有数字0~7;编译器标记其他数字为错误。017是一个合法的八进制数(相当于基数为10的数值15)。

常量值前带0x被认为是十六进制数(基数为16)。基数为16的数值只能含有数字0~9和字母a~f或A~F。0x1fe是一个合法十六进制数(相当于基数为10的数值510)。

浮点数可以含有小数点和指数幂(用e表示,意思是“10的幂”)。小数点和e都可以任选。如果给一个浮点变量赋一个常量值,编译器会取得这个常量值并把它转换为浮点数(这个过程是隐式类型转换(implicit type conversion)的一种形式)。但是,使用小数点或e对于提醒读者当前正在使用的是浮点数是一个好主意;一些更旧的编译器也会需要这种暗示。

合法的浮点常量值包括:1e4、1.0001、47.0、0.0和-1.159e-77。我们可以对数加后缀强加浮点数类型:f或F强加float型,L或l强加long double型,否则是double型。

字符常量是用单引号括起来的字符,如‘A’、‘0’、‘’。注意字符‘0’(ASCII 96)和数值0之间存在巨大差别。用“反斜线”表示一些特殊的字符:‘\n’(换行),‘\t’(制表符),‘\’(反斜线),‘\r’(回车),‘\"’(双引号),‘\'’(单引号),等等。也可以用八进制表示字符常量(如‘\17’)或用十六进制表示字符常量(如‘\xff’)。