C++Primer
中并没有对const过多的解析,只说明为是一个使变量不可修改的限定符.但是仅仅知道这点对于我来说是远远不够的,const是怎么做到的限制修改?谁在帮const做这个限制?编辑器是怎么实现不可修改的?在认识const之前 我知道C++中唯一不可修改的就是常量,例如:
int i = 1000;
这个1000就是常量,除了修改生成的文件之外 任何方式都无法修改这个1000 .(修改生成的文件是怎么修改?例如生成了exe可执行文件,直接定位到代码区 找到这个变量定义的地方 把 1000的字节码E8 03 00 00改了..).
下面我们尝试下修改const声明的常量:
void main() { const int q = 1000; printf("q1 = %d\r\n",q); int *pQ = (int*)&q; *pQ = 50; printf("q2 = %d\r\n",q); printf("pQ = %d\r\n",*pQ); printf("q address:%d\r\n",&q); printf("pQ address:%d\r\n",pQ); getchar(); }
这段代码编译运行后输出:
q1 = 1000 q2 = 1000 pQ = 50 q address:1702152 pQ address:1702152
显然 const 常量 q 前后输出的都是1000.而q的指针修改后输出的是50.q的地址和pQ所指向的地址一样,输出的内容却不一样.这就让人奇怪了.按道理说 同一块内存(1702152) 改变了值之后所输出的内容应该也都是一样的(50)才对. 我们反编译看看编译器都做了什么:
const int q = 1000; 002C35EE mov dword ptr [q],3E8h printf("q1 = %d\r\n",q); 002C35F5 mov esi,esp 002C35F7 push 3E8h 002C35FC push 2CCC90h 002C3601 call dword ptr ds:[2D045Ch] 002C3607 add esp,8 002C360A cmp esi,esp 002C360C call __RTC_CheckEsp (02C1325h) int *pQ = (int*)&q; 002C3611 lea eax,[q] 002C3614 mov dword ptr [pQ],eax *pQ = 50; 002C3617 mov eax,dword ptr [pQ] 002C361A mov dword ptr [eax],32h printf("q2 = %d\r\n",q); 002C3620 mov esi,esp 002C3622 push 3E8h 002C3627 push 2CCCDCh 002C362C call dword ptr ds:[2D045Ch] 002C3632 add esp,8 002C3635 cmp esi,esp 002C3637 call __RTC_CheckEsp (02C1325h) printf("pQ = %d\r\n",*pQ); 002C363C mov esi,esp 002C363E mov eax,dword ptr [pQ] 002C3641 mov ecx,dword ptr [eax] 002C3643 push ecx 002C3644 push 2CDAB8h 002C3649 call dword ptr ds:[2D045Ch] 002C364F add esp,8 002C3652 cmp esi,esp 002C3654 call __RTC_CheckEsp (02C1325h) printf("q address:%d\r\n",&q); 002C3659 mov esi,esp 002C365B lea eax,[q] 002C365E push eax 002C365F push 2CCC70h 002C3664 call dword ptr ds:[2D045Ch] 002C366A add esp,8 002C366D cmp esi,esp 002C366F call __RTC_CheckEsp (02C1325h) printf("pQ address:%d\r\n",pQ); 002C3674 mov esi,esp 002C3676 mov eax,dword ptr [pQ] 002C3679 push eax 002C367A push 2CDAC4h 002C367F call dword ptr ds:[2D045Ch] 002C3685 add esp,8 002C3688 cmp esi,esp 002C368A call __RTC_CheckEsp (02C1325h)
注:3E8h = 1000,32h = 50
由上面汇编代码可以看出.编译器把代码中的所有q都用3E8H代替了.也就是说 const定义的常量 在编译器生成阶段被替换成真实值了.所以无论你怎么修改const变量名所指的内存,其实都是没有用处的.因为在程序生成之后 所有的q 都被替换了.即使你在你的IDE编辑器中调试的时候看到q所指的是修改后的值50.
好了,这个拿走了