总结:这个跟计算机语言类别和编译器有关,本文是在linux环境下说明的.
分两种情况:
1. C语言:
2. C++语言:
/*! * \Description:
* \author scictor <scictor@gmail.com> * \date 3 */ #include <stdio.h> ;// 常量数据区,只读,指针修改导致程序Segmentation fault.const
string myglobal(
"global"
); //
const_cast方式修改,不会引起崩溃.
int main(int argc, char *argv[]) { int *pg_i = (int *)&g_i; *pg_i = ; printf("%p %d %p %d\n", &g_i, g_i, &pg_i, *pg_i);string* p=
const_cast
<string*>(&myglobal);
*p=
"local"
;
//这里强行改变了值
printf
(
"%s\n"
,myglobal.c_str());
; int *pa = (int *)&a; *pa = ; printf("%p %d %p %d\n", &a, a, pa, *pa); ; int *pi = (int *)(&i); *pi = ; printf("%p %d %p %d\n", &i, i ,pi, *pi); ; } /* 1.对于C语言: 先看结果: $ gcc -g -Wall const.c -o xmain $ ./xmain 0x7fff0146a9f8 3 0x7fff0146a9f8 3 0x7fff0146a9fc 32 0x7fff0146a9fc 32 解释: const数据放在常量数据区(constant segment),应用程序结束后,由操作系统释放. C标准规定,对于修改const变量属于未定义行为. 2.对于C++语言而言: 先看结果: $ g++ -g -std=c++11 -Wall const.cpp -o xmain $ ./xmain 0x7fffed0c89c8 10 0x7fffed0c89c8 3 0x7fffed0c89cc 32 0x7fffed0c89cc 32 解释: 根据C++标准,对于修改const变量,属于:未定义行为(指行为不可预测的计算机代码),这样一来此行为取决于各种编译器的具体实现(即不同编译器可能表现不同)。 没有加volatile修饰符,即此处编译器进行了优化,没有从内存中读,直接从符号表中取出的. 结果表现为:指针 pa 和 &a(a的地址)值却是一样的,但输出结果不同. 这就是C++中的常量折叠:指const变量(即常量)值放在编译器的符号表中,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化。 而在此基础上加上volatile修改符,即告诉编译器该变量属于易变的,不要对此句进行优化,每次计算时要去内存中取数. 总结: 修改const常量值受到以下因素影响: 实质原因: C和C++语言标准规定不同(存储位置不同,不同限定关键字和读取规则不同): 在C语言中,用const定义的常量其实是值不能修改的变量,因此会给它分配存储空间,c++的编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高. */