什么是常量?相信绝大多数写过程序的人见到这两个字的第一反应就是——不能更改的量。没问题,书本上这样告诉我们,编译器也这样告诉我们,好像常量就真的是那么简单,纯粹,让人心安理得的去使用它,不需要任何顾虑。但事实并没有想象中的那么单纯。
1.常量并不一定是常量
int main()
{
const int x=3;
}
这是一个“假常量”,当我们在下边敲出 x=4; 这样的代码时,编译器根本不会让你通过,至于为什么说它是假的,因为编译器可以被轻而易举的绕过去。
首先我们来看看表面现象,对p的一顿操作让p成功的指向了x,我们成功的绕过了编译器,获得了指向常量x的非常量指针,并且没有动用const_cast,当我们窃喜可以修改这个“常量”x的值的时候,运行结果给我们当头一棒,x的值并没有改。难道是编译器明察秋毫发现我们的小伎俩了?不,编译器真的那么聪明是不会把结果显示出来的,甚至都不会让你通过编译。那为什么x的值没有改变呢?让我们来看看汇编代码。我先吧整体的代码贴出来再节选部分进行分析。
const int x=3;
00176E2E mov dword ptr [x],3
int y=4;
00176E35 mov dword ptr [y],4
int*p=&y;
00176E3C lea eax,[y]
00176E3F mov dword ptr [p],eax
p=p-(&y-&x);
00176E42 lea eax,[y]
00176E45 lea ecx,[x]
00176E48 sub eax,ecx
00176E4A sar eax,2
00176E4D shl eax,2
00176E50 mov edx,dword ptr [p]
00176E53 sub edx,eax
00176E55 mov dword ptr [p],edx
*p=5;
00176E58