今天在看面经的时候无意间看到了const修饰栈变量的一些奇奇怪怪的事情,先来看一段代码
int main()
{
int a = 1;
int* pa = (int*)&a;
*pa = 2;
cout << "a = " << a << '\n';
return 0;
}
运行截图:
没有任何问题 pa指向a,通过pa可以修改a
再看一段:
int main()
{
const int a = 1; // 这里加了const修饰a
int* pa = (int*)&a;
*pa = 2;
cout << "a = " << a << '\n';
return 0;
}
这段代码与第一段代码区别不大,只是a被const修饰了,直接通过int*是不能指向const int* 的,所以这里强转一下,按常理说应该可以修改a的值,但我们看一下运行结果
a = 1?
别着急,我们再看一段代码
int main()
{
volatile const int a = 1; // 用volatile修饰const int
int* pa = (int*)&a;
*pa = 2;
cout << "a = " << a << '\n';
return 0;
}
这里用了volatile和const一起修饰a,运行结果:
可以发现a被成功改变了。
什么原因导致的呢?
初步理解可能是编译器对const修饰的栈变量进行了优化,比如直接将它的值直接内联到代码中,不为其分配实际的地址。
当加入了volatile修饰之后,不让编译器对const修饰的栈变量进行优化时,这样我们每次访问这个a都是从内存中存取,通过int* pa确实可以实际修改指向地址处的内容。