最近在看程序员面试宝典,看到const这块感觉有很大疑惑,查了很多资料,可以总结如下:
1.在C语言中
在C语言中,const修饰的变量不具有常量的特性,只是一个不可修改的变量,实质上仍然是变量,在编译期间无法知道它的值,不可以用作数组下标。
2.在C++中
在C++中,const就有很大不一样,C++中鼓励使用const来替代#define,在C++中对const定义的变量分为两种情况:
情况1(在.rodata段分配空间):
如果const用在全局或者使用了static关键字说明,例如extern const int i=10,static const int i=10。那么这个i就是一个常量(网上有人说真正意义上的常量),并且该常量是存放在.rodata段的,是无法通过取地址方式去修改的(具体情况见情况2),修改会报段错误。
情况2(不在.rodata段分配空间):
如果const用在局部并且没有使用static关键字,例如在main函数里面const int i=10*2+1,在这种情况下,如果对该常量:1)赋值是常量表达式(没有其它变量或者需要外界输入的值);2)不对该常量进行一些取地址类似的操作(&),就不会对i分配空间,仅仅是将其放在符号表中;否则,就会对i分配空间,而且这个空间是在栈上的,不同于全局的是分配在.rodata段上的。另外,注意,利用编译器反汇编的时候,可能会有一些假象,例如,在DEBUG模式下面的反汇编,编译器生成汇编代码为了能更好的调试,所以无论如何都会分配空间给const常量,但是如果你打开编译器的O2优化选项的话,就不会分配空间了。
不过,不论分不分配空间,只要该常量的赋值是常量表达式(没有其它变量或者需要外界输入的值),编译器都会做一个优化,叫做常量折叠(const folding),简单来说,就是编译的时候,任何用到i的地方,都会直接用21去替换i。
a.有常量折叠
如果i的赋值是常量表达式(没有其它变量或者需要外界输入的值),即i的值不需要访问存储空间来确定,那么程序中任何出现i的地方就已经在编译期间被替换,即使通过取地址来修改这个值,也是相当于改变了一个副本而已,如下:
const int i=1; int *p=(int *)&i; *p=2; cout<<*p<<endl<<i<<endl; 输出结果: 2 1 |
这说明,i的值是确定的情况下,程序中任何出现i的地方都被1替换了。