大家都知道const修饰的变量是不可变的,但是到底是怎么实现的那,有方法修改只读变量的值吗,今天我们结合实验代码,分析下const关键字的实现原理
const变量
1.const修饰局部变量
int main(){
const int abc = 123;
printf("%d\n", abc);
abc = 234;
return 0;
}
我们会得到错误信息: E0137 表达式必须是可修改的左值
这种是编译器做了静态语法分析,约束变量abc不能被修改。
验证逻辑:
1. 使用整型指针指向abc变量的地址
2. 通过指针修改const修饰的abc变量的值为234
3.查看abc变量的值,如果是234,说明const修饰的局部变量之所以不能被修改是因为编译器做了静态语法检查
int main(){
const int abc = 123;
printf("%d\n", abc);
int* p = (int*) & abc;
*p = 234;
printf("%d\n", abc);
return 0;
}
查看abc变量的内容是0x7b就是十进制的123
执行完代码*p=234后我们可以发现abc变量内存地址对应的值确实被改了。
注:大家可以猜测下接下来要执行的printf("%d\n",abc)会在控制台输出123,还是234?欢迎大家留言讨论
2.const修饰全局变量
const int hah = 234;
int main() {
printf("%d\n", hah);
hah = 345;
int* p = (int*) & hah;
*p = 345;
printf("%d\n", hah);
return 0;
}
我们同样会得到错误信息: E0137 表达式必须是可修改的左值
这种是编译器做了静态语法分析,约束变量abc不能被修改。同时我们要验证是否有动态执行的验证逻辑。同样使用指针指向变量地址,然后强制修改变量的值,看结果
触发了访问异常,说明有动态执行的保护逻辑
总结:
1.const修饰的变量会受到编译器静态语法分析的保护,不能直接复制
2.const修饰的局部变量会分配到栈内存中,栈的内存属性是可写的,所以可以通过指针强制修改,而const修饰的全局变量会被编译到只读属性的节中,程序运行起来只读变量所在的内存没有写属性,所以通过指针强制修改会触发访问异常
提问:
1. const修饰的全局变量可以在运行时被强制修改吗?
2. const修饰局部变量的实验中,指针成功修改const变量的值后,后面的printf语句应该输出什么123还是234?