/*
C/C++中规定,在变量前加const修饰符是将变量定义为常量,其值是不能修改的
但这个不能修改也只是针对编译器而言
*/
#include <stdio h="">
int main()
{
const int a = 2;
int *b,i = 0;
printf("%d\n",a);
b = (int*)&a;//强制转换一下,让编译通过
*b = 10;
__asm
{
push eax
mov eax,a//把变量a的值给寄存器EAX(上边已经用*b=10改变了a的值了)
mov i,eax//再把寄存器EAX的值给i
pop eax
}
printf("a:%d\n",a);//有使用a的地方全被改成push 2了,而并没有去a的内存空间取值
printf("*b:%d\n",*b);
printf("i:%d\n",i);//其实a的内存空间的数值是被改变掉的
//只是编译做了手脚,将有a出现的地方全改成a刚开始的值了
return 0;
}//VC6.0编译通过
/*以下是VC6.0调试的汇编代码*/
1: /*
2: C/C++中规定,在变量前加const修饰符是将变量定义为常量,其值是不能修改的
3:
4: 但这个不能修改也只是针对编译器而言
5: */
6:
#include <stdio.h>
7:
8:
int main()
9:
{
0040D720 55 push ebp
0040D721 8B EC mov ebp,esp
0040D723 83 EC 4C sub esp,4Ch
0040D726 53 push ebx
0040D727 56 push esi
0040D728 57 push edi
0040D729 8D 7D B4 lea edi,[ebp-4Ch]
0040D72C B9 13 00 00 00 mov ecx,13h
0040D731 B8 CC CC CC CC mov eax,0CCCCCCCCh
0040D736 F3 AB rep stos dword ptr [edi]
10:
const int a = 2;
0040D738 C7 45 FC 02 00 00 00 mov dword ptr [ebp-4],2
11:
int *b,i = 0;
0040D73F C7 45 F4 00 00 00 00 mov dword ptr [ebp-0Ch],0
12:
printf("%d\n",a);
0040D746 6A 02 push 2 /*是直接将2压入堆栈,并不是去取a的值*/
0040D748 68 1C 20 42 00 push offset string "%d/n" (0042201c)
0040D74D E8 3E 39 FF FF call printf (00401090)
0040D752 83 C4 08 add esp,8
13:
b = (int*)&a;//强制转换一下,让编译通过
0040D755 8D 45 FC lea eax,[ebp-4]
0040D758 89 45 F8 mov dword ptr [ebp-8],eax
14:
*b = 10;
0040D75B 8B 4D F8 mov ecx,dword ptr [ebp-8]
0040D75E C7 01 0A 00 00 00 mov dword ptr [ecx],0Ah
15:
__asm
16:
{
17: push eax
0040D764 50 push eax
18: mov eax,a
0040D765 8B 45 FC mov eax,dword ptr [ebp-4]
19: mov i,eax
0040D768 89 45 F4 mov dword ptr [ebp-0Ch],eax
20: pop eax
0040D76B 58 pop eax
21:
}
22: printf("a:%d\n",a);//有使用a的地方全被改成push 2了,而并没有去a的内存空间取值
0040D76C 6A 02 push 2 /*第二次使用到a,还是直接将定义时的值给压入堆栈*/
0040D76E 68 B4 2F 42 00 push offset string "a:%d/n" (00422fb4)
0040D773 E8 18 39 FF FF call printf (00401090)
0040D778 83 C4 08 add esp,8
23:
printf("*b:%d\n",*b);
0040D77B 8B 55 F8 mov edx,dword ptr [ebp-8]
0040D77E 8B 02 mov eax,dword ptr [edx] /*取a的内存空间的值*/
0040D780 50 push eax /*再压入堆栈*/
0040D781 68 AC 2F 42 00 push offset string "*b:%d\n" (00422fac)
0040D786 E8 05 39 FF FF call printf (00401090)
0040D78B 83 C4 08 add esp,8
24:
printf("i:%d\n",i);//其实a的内存空间的数值是被改变掉的
0040D78E 8B 4D F4 mov ecx,dword ptr [ebp-0Ch]
0040D791 51 push ecx
0040D792 68 A4 2F 42 00 push offset string "i:%d/n" (00422fa4)
0040D797 E8 F4 38 FF FF call printf (00401090)
0040D79C 83 C4 08 add esp,8
25: //只是编译做了手脚,将有a出现的地方全改成a刚开始的值了
26:
return 0;
0040D79F 33 C0 xor eax,eax
27:
}//VC6.0编译通过
0040D7A1 5F pop edi
0040D7A2 5E pop esi
0040D7A3 5B pop ebx
0040D7A4 83 C4 4C add esp,4Ch
0040D7A7 3B EC cmp ebp,esp
0040D7A9 E8 62 39 FF FF call __chkesp (00401110)
0040D7AE 8B E5 mov esp,ebp
0040D7B0 5D pop ebp
0040D7B1 C3 ret
/*
总结,const修饰的变量是由编译在编译连接阶段进行检测的,检测到有代码段修改了其值就会提示语法错误
而且每次使用该变量的值时,不是去内存空间去取,而是由编译直接将其值拿来参于编译连接
*/
2010-08-19