第4章和第10章中介绍过const。以const关键字声明的对象,其值不能通过赋值或递增、递减来修改。在ANSI兼容的编译器中,以下代码:
const int nochange; /* 限定nochange的值不能被修改 */
nochange = 12; /* 不允许 */
编译器会报错。但是,可以初始化const变量。因此,下面的代码没问题:
const int nochange = 12; /* 没问题 */
该声明让nochange成为只读变量。初始化后,就不能再改变它的值。
可以用const关键字创建不允许修改的数组:
const int days1[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
1. 在指针和形参声明中使用const
声明普通变量和数组时使用const关键字很简单。指针则复杂一些,因为要区分是限定指针本身为const还是限定指针指向的值为const。下面的声明:
const float * pf; /* pf 指向一个float类型的const值 */
创建了pf指向的值不能被改变,而pt本身的值可以改变。例如,可以设置该指针指向其他const值。相比之下,下面的声明:
float * const pt; /* pt 是一个const指针 */
创建的指针pt本身的值不能更改。pt必须指向同一个地址,但是它所指向的值可以改变。下面的声明:
const float * const ptr;
表明ptr既不能指向别处,它所指向的值也不能改变。
还可以把const放在第3个位置:
float const * pfc; // 与const float * pfc;相同
如注释所示,把const放在类型名之后、之前,说明该指针不能用于改变它所指向的值。简而言之,const放在左侧任意位置,限定了指针指向的数据不能改变;const放在*的右侧,限定了指针本身不能改变。
const关键字的常见用法是声明为函数形参的指针。例如,假设有一个函数要调用display()显示一个数组的内容。要把数组名作为实际参数传递给该函数,但是数组名是一个地址。该函数可能会更改主调函数中的数据,但是下面的原型保证了数据不会被更改:
void display(const int array[], int limit);
在函数原型和函数头,形参声明const int array[]与constint * array相同,所以该声明表明不能更改array指向的数据。
ANSI C库遵循这种做法。如果一个指针仅用于给函数访问值,应将其声明为一个指向const限定类型的指针。如果要用指针更改主调函数中的数据,就不使用const关键字。例如,ANSIC中的strcat()原型如下:
char *strcat(char * restrict s1, const char * restrict s2);
回忆一下,strcat()函数在第1个字符串的末尾添加第2个字符串的副本。这更改了第1个字符串,但是未更改第2个字符串。上面的声明体现了这一点。