C语言中的const
const修饰的变量是只读的,本质还是变量
const修饰的局部变量在栈上分配空间(改变这个空间的值,这个变量就会改变)
const修饰的全局变量在只读存储区分配空间
const只在编译期游泳有用,在运行期无用
const修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边
C语言中的const使得变量具有只读属性
const将具有全局生命周期的变量存储于只读存储区
const不能定义真正意义上的常量
C语言中通过enum定义的标识符才是真正意义上的常量,也就是说C语言中的真正意义上的常量只有枚举
const的C语言示例程序如下:
1 #include <stdio.h> 2 3 int main() 4 { 5 const int c = 0; 6 int* p = (int*)&c; 7 8 printf("Begin...\n"); 9 10 *p = 5; 11 12 printf("c = %d\n", c); 13 14 printf("End...\n"); 15 16 return 0; 17 }
执行结果如下:
可以看待const变量c的值被改变了。
我们将上面的程序写到const1.cpp文件中用g++编译器进行编译,执行结果如下:
添加一句打印,我们观察*p的值:
1 #include <stdio.h> 2 3 int main() 4 { 5 const int c = 0; 6 int* p = (int*)&c; 7 8 printf("Begin...\n"); 9 10 *p = 5; 11 12 printf("*p = %d\n", *p); 13 printf("c = %d\n", c); 14 15 printf("End...\n"); 16 17 return 0; 18 }
执行结果如下:
可以看到*p的值是5,这说明内存空间中的值确实改变了,但是c的值没有改变。
C++中的const:
C++在C语言的基础上对const进行了优化处理
当碰见const声明时在符号表中放入常量
编译过程中若发现使用常量则直接以符号表中的值替换
编译过程中若发现下述情况则给对应的常量分配存储空间(兼容C语言,保证C语言程序能编译过去)
对const常量使用了extern
对const常量使用了&操作符
注意:
C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值
符号表的示意图如下:
对比:
C++中的const与宏定义:
宏定义与const的示例程序如下:
1 #include <stdio.h> 2 3 void f() 4 { 5 #define a 3 6 const int b = 4; 7 } 8 9 void g() 10 { 11 printf("a = %d\n", a); 12 //printf("b = %d\n", b); 13 } 14 15 int main() 16 { 17 const int A = 1; 18 const int B = 2; 19 int array[A + B] = {0}; 20 int i = 0; 21 22 for(i=0; i<(A + B); i++) 23 { 24 printf("array[%d] = %d\n", i, array[i]); 25 } 26 27 f(); 28 g(); 29 30 return 0; 31 }
gcc的编译结果如下:
C语言中const修饰的是只读变量,也就是说19行的程序中数组的大小是由变量定义的,所以编译会出错。
用C++编译器编译上述的程序,结果如下:
对C++编译器来说,const修饰的变量会进入符号表,是常量,第19行会直接去符号表中取值,认为是常量所以不会报错。
上面的程序中f函数中定义的宏在g函数中可以直接使用,因为宏是由预处理器处理的,不存在作用域问题。编译器根本不知道宏是什么。
而如果使用const常量代替宏定义,则编译器就会进行作用域检查了。
小结:
与C语言不同,C++中的const不是只读变量
C++中的const是一个真正意义上的常量
C++编译器可能会为const常量分配空间
C++完全兼容C语言中const常量的语法特性