常量折叠

之前面试xx公司的时候被问到关于const常量折叠的问题,当时就挺懵逼的。。。
下去后,查了下,这个常量折叠还是蛮有意思的,工作中也竟然没有注意到这点,不过话说这种写法应该也没人会去写吧。。。
先贴上一段代码:

#include <iostream>
using namespace std;

int main()
{
	const int a = 10;
	int* pa = const_cast<int*>(&a);
	*pa = 20;

	printf("&a=%p\n", &a);
	printf("pa=%p\n", pa);
	printf("a=%d\n", a);
	printf("*pa=%d\n", *pa);

    return 0;
}

运行上面的代码,就会发现a的地址和pa指向的地址是一模一样的,但是,他们的取值却是不同的,a的值依旧为10,而*pa的值位20。
这个结果挺颠覆我们对指针的理解是不是。地址都是一样的,为何通过指针访问地址修改数据后,a的值没有被变化呢??
利用vs的反汇编调试,断点进去查看,发现汇编码是这样子的:

printf("a=%d\n", a);
00CF1F80  push        0Ah  
00CF1F82  push        offset string "a=%d\n" (0CF8BE8h)  
00CF1F87  call        _printf (0CF13F2h)  
00CF1F8C  add         esp,8  
printf("*pa=%d\n", *pa);
00CF1F8F  mov         eax,dword ptr [pa]  
00CF1F92  mov         ecx,dword ptr [eax]  
00CF1F94  push        ecx  
00CF1F95  push        offset string "*pa=%d\n" (0CF8B3Ch)  
00CF1F9A  call        _printf (0CF13F2h)  
00CF1F9F  add         esp,8  

通过这个汇编码就能看到,a的值实际上并不是通过内存取出来的,而是直接将0Ah,也就是10这个值直接拿出来了。而pa取值是通过寄存器来内存取值完成的。
这个其实就是所谓的const的内存折叠,其实就是编译器的优化手段,对于const会再预编译时就进行优化处理,其指向的值直接从常量表获取,而不再通过内存访问取值,以此来加快效率。
如果一定要修改const的值,可以加入关键字volatile即可。比如讲上述代码对a的定义改成const volatile int a = 10; 这样子便能告诉编译器,我们的a是可变的,每次取值编译器就会从内存获取。当然,这个volatile的具体优化也取决于编译器。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页