2.6 常量
前几节介绍的数据类型都是以变量形式进行演示的,在程序运行中可以修改其保存的数据。从字面上理解,常量是一个恒定不变的值,它在内存中也是不可修改的。如果在程序中出现1、2、3这样的数字或“Hello”这样的字符串,以及数组名称,它们都属于常量。程序在运行中不可修改它们的数据。
常量数据在程序运行前就已经存在,它们被编译到可执行文件中。当程序启动后,它们便会被加载进来。这些数据通常都会在常量数据区中保存,该节区的属性中是没有可写权限的,所以在对常量进行修改时,程序会报错。试图修改它们的数据都将引发异常,导致程序崩溃。
常量数据的地址减去基地址,便是它在文件中的偏移地址。以图2-12中字符指针所保存的地址为例,这个地址为常量字符串“Hello World!”的首地址。
图 2-12 常量字符串地址
在图2-12中,常量字符串的首地址为0x00423FA8,该程序的基地址为0x00400000,所在文件对应的偏移地址为:字符串首地址-基地址=0x00023FA8,使用十六进制查看器打开该程序可执行文件找到对应的数据,如图2-13所示。
图 2-13 常量字符串在文件中的位置
2.6.1 常量的定义
在C++中,可以使用宏机制#define来定义常量,也可以使用const将变量定义为一个常量。#define定义的常量名称,编译器对其进行编译时,会将代码中的宏名称替换成对应信息。宏的使用可以增加代码的可读性。const是为了增加程序的健壮性而存在的。常用字符串处理函数strcpy的第二个参数被定义为一个常量,这是为了防止该参数在函数内被修改,对原字符串造成破坏,宏与const的使用如代码清单2-10所示。
代码清单2-10 宏与const的使用
//定义NUMBER_ONE为常量1
#define NUMBER_ONE1
//将常量NUMBER_ONE赋值给const常量nVar
const int nVar=NUMBER_ONE;
//显示两者结果
printf("const=%d#define=%d\r\n",nVar, NUMBER_ONE);
代码清单2-10中使用#define定义了常量1,并赋值给const常量nVar。编译后,宏名称NUMBER_ONE将被替换成1。使用Microsoft Visual C++6.0编译此段代码,依次选择菜单Project→Settings→C/C++→Project Options→添加/P选项,如图2-14所示。
图 2-14 添加编译选项
此编译选项的功能是将预处理文件生成到文件中,编译后,对应的CPP文件夹中会产生一个“文件名.i”的文件。编译代码清单2-10中的代码,生成.i文件,打开该文件查看main函数中的代码信息。添加“/P”选项后,在连接过程中会产生错误,这是由于没有生成OBJ文件,而是将预处理信息写入了.i文件中,编译器找到不OBJ,无法进行连接。查看.i文件中的信息,如代码清单2-11所示。
代码清单2-11 预处理文件信息
int main(int argc, char*argv[])
{
const int nVar=1;//这里的宏NUMBER_ONE都被替换为数字1
printf("const=%d#define=%d\r\n",nVar,1);
return 0;
}