c++中的常量折叠

2 篇文章 0 订阅

何谓常量折叠?
常量折叠就是将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。可以算作一种编译优化。(预编译阶段)

接下来我们通过一段代码来分析一下了解一下常量折叠及其特性:

int main()
{
    const int a = 10;
    int b = 2*a;
    int c = b;
    int *p = (int*)&a;
    *p = 100;
    cout << a << endl;//输出10
    cout<< *p<<endl;//输出100
    return 0;
}

1 编译器会为该常量在栈上分配一块空间。

const int a = 10;
0099446E  mov         dword ptr [a],0Ah  

a是一个常量,按理说常量是存储在代码段的,可通过反汇编可以清楚地看到编译器确实为a在栈上分配了一块空间。
在这一点上const常量和宏是有区别的,宏在预编译阶段就完成了替换,编译器并不会为宏分配空间。

2 代码中遇上a的地方,直接替换为a的值
下面我们来比较一下常量折叠和正常变量的赋值

    int b = 2*a;//常量折叠赋值
00994475  mov     dword ptr [b],14h//真正的实现形式是int b=2*10  
    int c = b;//正常变量赋值
0099447C  mov     eax,dword ptr [b]//借助寄存器eax把b的值传递给c  
0099447F  mov     dword ptr [c],eax

3
大家是否对上面代码中最后的输出结果有疑惑?
指针p指向a在栈上的空间,而且明明通过*p=100对该空间上的内容作出了改变,为什么输出的a依旧是10呢?
话不多说,我们来看反汇编:

    int *p = (int*)&a;
00994482  lea         eax,[a]  //通过寄存器eax把a的地址给指针p
00994485  mov         dword ptr [p],eax  
    *p = 100;
00994488  mov         eax,dword ptr [p]  
0099448B  mov         dword ptr [eax],64h//修改p指向的空间的内容 
    cout << a << endl;
00994491  mov         esi,esp  
00994493  push        99149Ch  
00994498  mov         edi,esp  
0099449A  push        0Ah//出现a的地方直接用10代替  
0099449C  mov         ecx,dword ptr ds:[9A00ECh]  
009944A2  call        dword ptr ds:[9A0094h]  
009944A8  cmp         edi,esp  
009944AA  call        __RTC_CheckEsp (0991325h)  
009944AF  mov         ecx,eax  
009944B1  call        dword ptr ds:[9A00F4h]  
009944B7  cmp         esi,esp  
009944B9  call        __RTC_CheckEsp (0991325h)  

从上面的汇编代码中可以看到,a所在地址上的内容确实已经被p所修改,a的值已被改变,但是在输出a的时候,编译器输出的并不是该空间上的内容,而是直接用10替换了。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值