C 语言中 const 修饰符:
-
const 修饰的变量不是真正意义上的常量,而是一个
常变量
-
无法直接修改,但是
可以间接修改
变量的值。会分配内存空间
,因此可以通过指向其地址空间的指针去修改其内容。const int b = 10; int * p = (int *)&b; *p = 30; printf("%x\n" , &b); // 313b1df4 printf("%x\n" , p); // 313b1df4 printf("%i\n" , b); // 30,可以发现C中的常量的值这么被修改了,却没有任何报错 printf("%i\n" , *p); // 30
-
不能把const看成一个编译期间的常量
const int bufsize=100; char buf[bufsize]; // 编译错误,因为bufsize会占用内存的某个地方,因此 C 编译器不知道他在编译时候的值
-
C默认是
外部连接
的。C编译器把它作为一个生命,指明在别的地方有内存分配。
const bufsize; // 正常编译。C是外部连接,看作一个声明
C++ 中 const 修饰符:
-
const 修饰的变量是真正的
常量
,必须初始化
。const bufsize; // C中正常。C++编译报错,常量必须初始化
-
C++默认是
内部连接
的。const 对象默认只能在当前文件中访问,不能再别的文件中访问(除非显式的指定extern) -
通常不会为其分配内存
,这些常量一般以键值对的形式存放在一张符号表
中,而不给其分配内存,编译过程
中若发现该常量直接以符号表中的值替换。 -
但是当使用 extern 修饰变量时(或者获取常量的地址等),则必须为变量分配空间。因为extern表示使用外部连接,说明会有其他的编译单元会使用寻址放来来引用它,因此就必须拥有自己的地址。
-
C++常量折叠
:即将const常量放在符号表中,而不给其分配内存。编译器直接进行替换优化,除非用到存储空间的时候,编译器才会去分配空间,但之后获取b的值仍从符号表中读取,不过存储空间中的值如何变化const int b = 10; int * p = (int *)&b; *p = 30; printf("%x\n" , &b); // 313b1df4 printf("%x\n" , p); // 313b1df4 printf("%i\n" , b); // 10,可以发现和 C 语言不同,常量的值并没有被修改 printf("%i\n" , *p); // 30