常量折叠
今天意外见识了这个名词是在CSDN帖子里http://topic.csdn.net/u/20120406/03/f59790a9-67b8-479c-9f43-9bc413fae761.html?95101
其实这个困惑早就出现了,记得最早是看到了这篇文章http://www.cnblogs.com/wenzhang/archive/2011/12/30/2308052.html,当时还请教了作者,但始终没有说服自己的理由,今天 再看到确实有种重见老朋友的感觉,所以就上网搜搜这方面的帖子了。
首先来看一个简单的例子吧:
#include <iostream>
using namespace std;
int main()
{
const int a=6;//const修饰必须初始化
int *p=(int*)&a;
*p=8;
cout<<"a的地址为:"<<&a<<"\t"<<"a的值为:"<<a<<endl;
cout<<"p的地址为:"<<p<<"\t"<<"p指向变量的值为:"<<*p<<endl;
return 0;
}
运行结果:
a的地址为:0012FF7C a的值为:6
p的地址为:0012FF7C p指向变量的值为:8
一个内存地址竟然同时存两个值,有点诧异。这就牵涉到了常量折叠。
常量折叠的概念:在编译器里进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表,可以算作一种编译优化。
在编译器的优化的过程中,会把用const修饰的变量以内容替换掉,如宏似的:#define pi 3.14,当然这种是出现在预编译阶段,在运行阶段时,它的内存里的内容是可以改变的。
对于const int a=6,可能有如此疑问:a是什么,存在哪里,6又是什么,存在哪里?我不会将a看作常量,我更愿称之为用const修饰的变量。所谓变,我只的是其代表内存中所存的内容会变,要问a与一般变量有什么不同,无非就是被const修饰了。那么被const修饰了又是什么意思呢,如:const int a=6,其实这个语句是对a的声明,编译器一开始就知道a的,a是一个符号,放在符号表中,其代替了6,也就是说6也可以看作是一种符号,所以a就是6,6就是a,当然是相对来说的。相当6还是不同于 a的,6是文字常量,字面常量。那么6存在哪呢,其实管它在哪呢,因为它毕竟是不能存址的。
可以说,c++里的常量折叠(或者常量替换)是将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。
参考:
(1)http://www.cppblog.com/xmli/archive/2010/11/23/134425.html
(2)http://topic.csdn.net/u/20071016/13/4617d907-23ac-489e-81dc-90a80b118f0b.html