地球人都知道,在C/C++中,const关键字修饰变量时,该变量在初始化后就不允许被改变,如:

const int b;//C++17下出错,const变量初始化时就需要赋值。

const int b = 1;
b=2;//出错,const变量不允许通过这种方式改变。

然而,《Thinking in C++》第92页指出,可以通过对const变量的地址的强制类型转换实现改变const变量的值。

const int i = 0;
int *j = const_cast<int *)(&i); //也可以沿用C中的强制类型转换
*j = 1;
printf("%d %d",i,*j);
//结果是 0 1

奇怪的是,最后的结果通过i输出为原值0,通过指针解引用访问为修改值1,而且从debugger中看也是修改值1。

原来,由于编译器优化,编译器在遇见a时直接从寄存器读取初值,而不再从内存中读取,导致通过指针修改的a无法反应出来。也就是说,讲道理,const修饰的变量大多只能阻止程序员直接通过变量名修改,而无法封堵其他修改途径。

一个例外是,全局const变量无法通过指针方式修改其值,将会出现运行时错误。

const int a = 0;
int main(){
    int* j= const_cast<int*>(&a);
    *j =1; // 此行报运行时错误
    printf("%d,%d",a,*j);
    return 0;
}

在上面的第一行加上volatile修饰符,告诉编译器此变量“不知何时会改变”,相当于禁用编译器对此变量的优化。

volatile const int i = 0;
int *j = const_cast<int *)(&i); //也可以沿用C中的强制类型转换
*j = 1;
printf("%d %d",i,*j);
//结果是 1 1
Last modification:May 2nd, 2019 at 10:33 pm
If you think my article is useful to you, please feel free to appreciate