const 在实际编程中用得并不多,const 是 constant 的缩写,意思是“恒定不变的”!它是定义只读变量的关键字,或者说 const 是定义常变量的关键字。
说 const 定义的是变量,但又相当于常量;说它定义的是常量,但又有变量的属性,所以叫常变量。用 const 定义常变量的方法很简单,就在通常定义变量时前面加 const 即可,如:
const int a = 10;
const 和变量类型 int 可以互换位置,二者是等价的,即上条语句等价于:
int const a = 10;
那么用 const 修饰后和未修饰前有什么区别呢?它们不都等于 10 吗?
用 const 定义的变量的值是**不允许改变的,即不允许给它重新赋值,即使是赋相同的值也不可以。**所以说它定义的是只读变量。这也就意味着必须在定义的时候就给它赋初值。
如果定义的时候未初始化,我们知道,对于未初始化的局部变量,程序在执行的时候会自动把一个很小的负数存放进去。这样后面再给它赋初值的话就是“改变它的值”了,即发生语法错误。
用 const 修饰的变量,无论是全局变量还是局部变量,生存周期都是程序运行的整个过程。全局变量的生存周期为程序运行的整个过程这个是理所当然的。而使用 const 修饰过的局部变量就有了静态特性,它的生存周期也是程序运行的整个过程。我们知道全局变量是静态的,静态的生存周期就是程序运行的整个过程。但是用const修饰过的局部变量只是有了静态特性,并没有说它变成了静态变量。
我们知道,局部变量存储在栈中,静态变量存储在静态存储区中,而经过 const 修饰过的变量存储在内存中的“只读数据段”中。只读数据段中存放着常量和只读变量等不可修改的量。
数组的长度不能是变量: 虽然 const 定义的是只读变量,就相当于是定义一个常量。但是只读变量也是变量,所以 const 定义的变量仍然不能作为数组的长度。C++ 扩展了 const 的含义,在 C++ 中用 const 定义的变量也可作为数组的长度。
const 也可以和指针变量一起使用,这样可以限制指针变量本身,也可以限制指针指向的数据。const 和指针一起使用会有几种不同的顺序,如下所示:
int a = 1;
int b = 2;
// 情况一
const int *p1 = &a;
int const *p2 = &a;
// 指针所指向的数据是只读的,也就是 p1、p2 本身的值可以修改(指向不同的数据),但它们指向的数据不能被修改。
// 即:
// *p1 = 3; 报错,不能修改指向的数据
// p1 = &b; 有效,可以修改变量的指向
// 情况二
int * const p3 = &a;
// 指针是只读的,也就是 p3 本身的值不能被修改;
// 即:
// p3 = &b; 报错,不能修改指向的地址
// *p3 = 3; 有效,可以修改指向地址的值
// 情况三
// 指针本身和它指向的数据都是只读的
const int * const p4;
int const * const p5;
const 离变量名近就是用来修饰指针变量的,离变量名远就是用来修饰指针指向的数据,如果近的和远的都有,那么就同时修饰指针变量以及它指向的数据。
const 通常用在函数形参中,如果形参是一个指针,为了防止在函数内部修改指针指向的数据,就可以用 const 来限制。例如c语言标准库中的函数
size_t strlen ( const char * str );
int strcmp ( const char * str1, const char * str2 );
char * strcat ( char * destination, const char * source );
char * strcpy ( char * destination, const char * source );
使用 const 限制函数参数,不但可以防止数据被修改,还可以在调用的时候给予提示。
const char *
和char *
是不同的类型,不能将const char *
类型的数据赋值给char *
类型的变量。但反过来是可以的,编译器允许将char *
类型的数据赋值给const char *
类型的变量。
char *
指向的数据有读取和写入权限,而const char *
指向的数据只有读取权限,降低数据的权限不会带来任何问题,但提升数据的权限就有可能发生危险。
所以下面操作行不通:
#include
int main(){
const char *str1 = "a";
char *str2 = str1; // 报错,不能给const变量增加权限
return 0;
}
很多人在学习 const 的时候都会混淆它与 define 的区别。从功能上说它们确实很像,但它们又有明显的不同:
在c++中,一个const不必创建内存空间,而在c中,一个const总是需要一块内存空间。
c++中用const定义了一个常量后,将其写入符号表(symbol table),这使得它成为一个编译期间的常量,没有给变量分配内存,也没有了存储与读内存的操作,使得它的效率也很高。
int main(){
const int a = 2;
int* p = (int*)(&a);
*p = 30; // 直接修改const常量对应的内存空间中的值
cout<<&a<
运行结果:
0x7fffc7920804
0x7fffc7920804
2
30
通过指针修改const常量对应的内存空间中的值,这种修改不会影响到常量本身的值,因为编译器根本不会去进行内存空间的读取。这就是c++的常量折叠(constant folding),即将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。
除非需要用到const常量的存储空间,编译器迫不得已才会分配一个空间,但之后const常量的值仍旧从符号表中读取,所以不会影响const常量的值。
而在C语言中
int main()
{
const int a = 2;
int* p = (int*)(&a);
*p = 30;
printf("%x\n",&a);
printf("%x\n",p);
printf("%i\n",a);
printf("%i\n",*p);
return 0;
}
运行结果
18b1c0e4
18b1c0e4
30
30
c语言通过指针引用可以修改const修饰变量的值。
c 与 c++ 的 const 异同总结
extern
或者对变量取地址时,编译器会分配存储地址,变量存储在只读数据段。两个都受到了只读数据段的保护,不可修改。const int a
的时候,编译器会报重定义的错误。而在c++中,则不会,因为c++中的const默认是内部连接的。const关键字及其作用(用法),C语言const详解
c语言中的const的作用及解析
c和c++关于const的一些区别