在实际中,使用const定义的栈变量,最终还是一个变量,只是在编译期间对语法进行了检查,发现代码有对const修饰的变量存在直接修改行为则报错.
被const修饰过的栈变量本质上是可以被修改的.我们可以利用指针获取const修饰过的栈变量的地址,强制将const属性修饰去掉,就可以修改对应的数据内容了,如以下代码
#include <iostream>
int main()
{
const int n1 = 5;
int* p = (int*)&n1;
*p = 6;
int n2 = n1;
return 0;
}
对应的反汇编
push ebp //
mov ebp,esp //
sub esp,0ch // 开辟栈帧
mov dword ptr[ebp-4],5 //n1 = 5
lea eax,[ebp-4]
mov [ebp-8],eax //p = (int*)&n1
mov ecx,[ebp-8]
mov dword ptr[ecx],6 //*p = 6
mov dword ptr[ebp-0ch],5 //n2 = n1
xor eax,eax
mov esp,ebp
pop ebp
retn
在上述代码中,由于const修饰的变量n1被赋值一个数字常量5,编译器在编译过程中发现n1的初始值是可知的,并且被修饰为const.之后所有使用n1的地方都被替换为这个可预知的值,故
int n2 = n1;对应的汇编代码并没有将n1赋值给n2,而是用常量值5代替.如果n1初始化为一个未知的值则编译器不会做