本文对使用指针对const的值进行修改进行探讨。环境为ubuntu16.04,使用的编译环境如下
初始化
在C/C++中,const 变量的值需要在声明时便进行赋值,否则在编译时便会报错。
#include <iostream>
using namespace std;
int main() {
const int a;
a = 10;
return 0;
}
const指针
对于指向const变量类型的指针,在声明时,也需要声明为const类型的指针。
#include <iostream>
using namespace std;
int main() {
const int a = 10;
int *p = &a;
return 0;
}
修改程序正确后,可以正确的输出a的地址,a的值,p和*p;
#include <iostream>
using namespace std;
int main() {
const int a = 10;
const int *p = &a;
cout << "&a = " << &a << " a = " << a << endl;
cout << "p = " << p << " *p = " << *p << endl;
return 0;
}
使用const指针修改a的值
接下来,我们尝试使用指针p修改a的值。
#include <iostream>
using namespace std;
int main() {
const int a = 10;
const int *p = &a;
*p = 20;
cout << "&a = " << &a << " a = " << a << endl;
cout << "p = " << p << " *p = " << *p << endl;
return 0;
}
可以看到,当我们尝试使用const指针p尝试修改a的值时,在编译过程中会提示出错。
引入非const指针
既然使用const指针无法修改a的值,那么使用非const指针能否改变a的值呢。
#include <iostream>
using namespace std;
int main() {
const int a = 10;
const int *p = &a;
int *q = const_cast<int*>(p);
*q = 20;
cout << "&a = " << &a << " a = " << a << endl;
cout << "p = " << p << " *p = " << *p << endl;
cout << "q = " << q << " *q = " << *q << endl;
return 0;
}
当我们将程序改为上面的样子之后,尝试进行编译,发现编译成功,然后运行程序,可以看到如下的输出。
从结果可以看到,*p和*q的值确实发现了改变,但是a的值仍然是不变的。而且,我们看到,从输出中,p和q确实是指向了变量a的地址。
这证明使用非const指针确实修改了改地址中的值,但是为什么a的值仍然不变呢?
结论
经过查找各种资料,最后看到一种结论认为比较可靠(有人说时const_cast的问题,但个人认为下面的说法更好一点)
1. const全局变量存储在全局存储空间,其值只有可读属性,不能修改;
2. const局部变量存储在堆栈中,可通过指针修改其值;
3. const变量在预处理是处理,编译器只对其值读取一次。
也就是说,在编译时,编译器对a进行一次读取,然后将其视为一个常量,每次出现a时,便用改常亮进行替代。(个人理解)
在上述的结论中,提及到const变量在局部与全局间有区别。因此,对全局情况进行验证。将const int a = 10;
移动到全局部分,然后编译运行。
#include <iostream>
using namespace std;
const int a = 10;
int main() {
const int *p = &a;
int *q = const_cast<int*>(p);
*q = 20;
cout << "&a = " << &a << " a = " << a << endl;
cout << "p = " << p << " *p = " << *p << endl;
cout << "q = " << q << " *q = " << *q << endl;
return 0;
}
从上图看到,编译时是没有错误的,但是运行程序时,出现了段错误。