被 const
关键字修饰的变量,它的值不能被改变,在整个作用域中都保持固定。例如
const int MaxNum = 100;
这样 MaxNum 的值就不能被修改了,任何对 MaxNum 赋值的行为都将引发错误:
MaxNum = 90; //错误,试图向 const 变量写入数据
我们经常将 const 变量称为常量(Constant)。创建常量的格式通常为:
const type name = value;
// 或者
type const name = value;
推荐采用第一种方式,不采用第二种方式。另外建议将常量名的首字母大写,以提醒程序员这是个常量。
由于常量一旦被创建后其值就不能再改变,所以常量必须在定义的同时赋值(初始化),后面的任何赋值行为都将引发错误。
const和指针
const
也可以和指针变量一起使用,这样可以限制指针变量本身,也可以限制指针指向的数据。
const
和指针一起使用会有几种不同的顺序,如下所示:
const int *p1;
//或者
int const *p1;
int * const p2;
在最后一种情况下,指针是只读的,也就是 p2 本身的值不能被修改;在前面两种情况下,指针所指向的数据是只读的,也就是 p1、p2 本身的值可以修改(指向不同的数据),但它们指向的数据不能被修改。
当然,指针本身和它指向的数据都有可能是只读的,下面的两种写法能够做到这一点:
const int * const p3;
//或者
int const * const p3;
可以这样来记忆:const 离变量名近就是用来修饰指针变量的,离变量名远就是用来修饰指针指向的数据,如果近的和远的都有,那么就同时修饰指针变量以及它指向的数据。
const和函数形参
const
通常用在函数形参中,如果形参是一个指针,为了防止在函数内部**修改指针指向的数据**,就可以用 const 来限制。例如
int strnchr (const char *arr){}
这样可以防止在函数内部修改 arr 指向的字符串。
const 和非 const 类型转换
当一个指针变量 str1 被 const 限制时,并且类似 const char *str1
这种形式,说明指针指向的数据不能被修改。如果将 str1 赋值给另外一个未被 const 修饰的指针变量 str2,就有可能发生危险。因为通过 str1 不能修改数据,而赋值后通过 str2 能够修改数据了,意义发生了转变,所以编译器不提倡这种行为,会给出错误或警告。
也就是说,const char *
和 char *
是不同的类型,不能将 const char *
类型的数据赋值给 char *
类型的变量。但反过来是可以的,编译器允许将 char *
类型的数据赋值给 const char *
类型的变量。
const对象默认为文件的局部变量
在全局作用域里定义非const变量时,默认它在整个程序中都可以访问,我们可以把一个非const变量定义在一个文件中,假设已经做了合适的声明,就可以在另外的文件中使用这个变量:
// file01
int count = 0;
// file02
extern int count; // 使用 file01 中定义的count变量
++count;
与其他变量不同,在全局作用域声明的const变量默认是属于文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。通过指定const变量为 extern
,就可以在整个程序中访问const对象。
// file01
extern const int count = 1;
// file02
extern int count; // 使用 file01 中定义的count变量
注意:非const变量默认为
extern
。要使const变量能够在其他文件中访问,必须在文件中显式地指定它为extern
。