一、const局部变量可以通过指针修改
先看一道题,以下程序输出的是:
#include <iostream> using namespace std; int main(void) { const int a = 100; int* p = (int*)(&a); *p = 200; cout << "a = " << a << ", *p = " << *p << endl; cout << "&a:" << (int*)& a << endl; cout << "p:" << p << endl; return 0; }
- A. 编译或者运行阶段报错
- B. a = 100, *p = 100
- C. a = 200, *p = 200
- D. a = 100, *p = 200
- E. a = 200, *p = 100
我们最有可能会选择A,因为以前总听到const修饰的变量不能改变;但也可能会选择C,因为学习了指针之后,我们知道了通过指针可以更改const变量的值。但实际答案却是D。
因为变量a是经过const修饰的,在C++中,const修饰的内容就被当成常量了,并且在编译时会进行宏替换处理,即只读取a一次,保存到栈空间中,下次使用的时候不再从原来的内存中读取。实际上a的内容已经被修改了。
此时我们可以加上volatile
关键字修饰a变量,这里volatile
关键字的作用是保证变量的内存可见性,即每次访问时都要到内存中重新读取。
volatile const int a = 100;
此时就能看到我们想看到的结果了。
二 const 全局变量不可以通过指针修改
这里将上面的a变量设置为全局变量:
#include <iostream> using namespace std; const int a = 100; int main(void) { int* p = (int*)(&a); *p = 200; cout << "a = " << a << ", *p = " << *p << endl; cout << "&a:" << (int*)& a << endl; cout << "p:" << p << endl; return 0; }
此时运行就会报错了,因为此时a是const全局变量,存放在全局区的,对其只有读权限没有写权限,因此即使通过指针也不能对其进行修改。
三、总结
- const全局变量存放在在全局区的,对其只有读权限没有写权限,因此即使通过指针也不能对其进行修改。
- const局部变量存放在堆栈区的,可以通过指针对其进行修改。
- const变量在预处理时会进行宏替换,编译器只对其值读取一次。