反汇编解析#define和const的区别

#define是一个真常量,而const却是由编译器判断实现的常量,严格来说是一个伪常量;
在实际中,由const定义的常量其实仍然是一个变量,只是编译器在编译过程中进行了检查,发现修改就会报错;

如果利用指针得到const int变量的地址,然后根据地址强制改变这个变量的值会有什么情况呢?编译器会不会报错?
变量值会不会改变?

C++代码如下:

    void main()
001    {     const int nVar=5;
002     int *p=(int*)(&nVar);
003     *p=7;
004     int _cgd=nVar;
005     cout<<"_cgd="<<_cgd<<endl;
006    }
很遗憾,结果输出为:5
当程序执行到004的时候我们打开调试里的Variables表:
知道其实nVar的值已经被改动;
继续执行到0005

可以发现虽然nVar的值早已修改为7,但是通过004语句的赋值并没有使得_cgd=7;
这是因为nVar的值是已经确定的;虽然你可以通过内存修改它的值,改变这个变量在内存中的二进制序列;但是
凡是以后代码中有nVar的出现, 一律会被编译器优化为初始值,也就是:5;而并不是将当前的nVar实际值进行赋值;

将上述C++代码反汇编:
12:   void main()
13:   {
004015C0 55                   push        ebp
004015C1 8B EC                mov         ebp,esp
004015C3 83 EC 4C             sub         esp,4Ch
004015C6 53                   push        ebx
004015C7 56                   push        esi
004015C8 57                   push        edi
004015C9 8D 7D B4             lea         edi,[ebp-4Ch]
004015CC B9 13 00 00 00       mov         ecx,13h
004015D1 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
004015D6 F3 AB                rep stos    dword ptr [edi]//以上为子函数初始化过程;
14:       const int nVar=5;
004015D8 C7 45 FC 05 00 00 00 mov         dword ptr [ebp-4],5
15:       int *p=(int*)(&nVar);
004015DF 8D 45 FC             lea         eax,[ebp-4]
004015E2 89 45 F8             mov         dword ptr [ebp-8],eax//将变量nVar偏移地址赋值给[ebp-8],也就是int *p;
16:       *p=7;
004015E5 8B 4D F8             mov         ecx,dword ptr [ebp-8]
004015E8 C7 01 07 00 00 00    mov         dword ptr [ecx],7//通过偏移地址将nVar的内容修改为:7
17:       int _cgd=nVar;
004015EE C7 45 F4 05 00 00 00 mov         dword ptr [ebp-0Ch],5// 重点:编译器直接将nVar解释为:5;虽然此时内存中的内容其实为:7
此过程为编译器的优化过程;
18:       cout<<"_cgd="<<_cgd<<endl;
004015F5 68 C8 10 40 00       push        offset @ILT+195(std::endl) (004010c8)
004015FA 8B 55 F4             mov         edx,dword ptr [ebp-0Ch]
004015FD 52                   push        edx
004015FE 68 1C E0 46 00       push        offset string "_cgd=" (0046e01c)
00401603 68 90 BE 47 00       push        offset std::cout (0047be90)
00401608 E8 7D FC FF FF       call        @ILT+645(std::operator<<) (0040128a)
0040160D 83 C4 08             add         esp,8
00401610 8B C8                mov         ecx,eax
00401612 E8 E8 FA FF FF       call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
00401617 8B C8                mov         ecx,eax
00401619 E8 C2 FB FF FF       call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
19:   }
0040161E 5F                   pop         edi
0040161F 5E                   pop         esi
00401620 5B                   pop         ebx
00401621 83 C4 4C             add         esp,4Ch
00401624 3B EC                cmp         ebp,esp
00401626 E8 75 F3 01 00       call        __chkesp (004209a0)
0040162B 8B E5                mov         esp,ebp
0040162D 5D                   pop         ebp
0040162E C3                   ret

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值