C/C++中const变量与指针所指内容的改变

来源:互联网 发布:mac无法切换输入法 编辑:程序博客网 时间:2024/06/16 21:52

先看一个很非常相当基础的C的代码哈~

void main(){      const int a=5;      int * b=(int*)&a;      *b=8;      printf("%d",a);}

大家先想想这个地方的输出到底应该是什么吧!

为了大家看的更清楚一些,我把程序稍稍修改一些,如下:

#include <cstdio>int main(){ const int a=5; int * b=(int*)&a; printf("%d\n",b); printf("%d\n",*b); *b=8; printf("%d\n",a); printf("%d\n",*b); return 0;}

结果输出:1245024558说明*b=8确实有替a所在的地址赋值。我在vs2008下编译输出汇编文件,摘选main函数部分汇编代码,加上我的理解注释,如下:_b$ = -20      ; size = 4_a$ = -8      ; size = 4_main PROC      ; COMDAT; 4    : { push ebp mov ebp, esp //esp为堆栈指针,ebp=esp sub esp, 216    ; 000000d8H push ebx push esi push edi lea edi, DWORD PTR [ebp-216] mov ecx, 54     ; 00000036H mov eax, -858993460    ; ccccccccH rep stosd; 5    :  const int a=5; mov DWORD PTR _a$[ebp], 5 //变量a存放在堆栈区,赋值为5; 6    :  int * b=(int*)&a; lea eax, DWORD PTR _a$[ebp] mov DWORD PTR _b$[ebp], eax  //b的值确实是变量a所在的地址; 7    :  printf("%d\n",b); mov esi, esp mov eax, DWORD PTR _b$[ebp] push eax push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ call DWORD PTR __imp__printf add esp, 8 cmp esi, esp call __RTC_CheckEsp; 8    :  printf("%d\n",*b); mov esi, esp mov eax, DWORD PTR _b$[ebp] mov ecx, DWORD PTR [eax] push ecx push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ call DWORD PTR __imp__printf add esp, 8 cmp esi, esp call __RTC_CheckEsp; 9    :  *b=8; mov eax, DWORD PTR _b$[ebp] mov DWORD PTR [eax], 8 //确实改变了a变量地址的内容; 10   :  printf("%d\n",a); mov esi, esp push 5  //这里就是问题所在,由于const关键字,编译器认为a与5是等价的,所以不再读取内存,而是直接用5代替a push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ call DWORD PTR __imp__printf add esp, 8 cmp esi, esp call __RTC_CheckEsp; 11   :  printf("%d\n",*b); mov esi, esp mov eax, DWORD PTR _b$[ebp] mov ecx, DWORD PTR [eax] push ecx push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ call DWORD PTR __imp__printf add esp, 8 cmp esi, esp call __RTC_CheckEsp; 12   :  return 0; xor eax, eax; 13   : }总结起来,就是const关键字令编译器认为a与常量5等价,所以输出的结果还是5。可以试试输出下面一句,有惊喜。原因我不解释了,自己想想吧:)printf("%d\n",*(((&a)+1)-1));

原创粉丝点击