使用-fpermissive转换const为non-const后出现的地址值矛盾问题
为何const变量存在同地址但取值不同的现象?
当使用-fpermissive编译以下代码时,输出显示指针a、p与&x指向同一内存地址,但*a/*p和x的取值却始终不同;去掉x的const修饰后,两者取值就会保持一致。背后的原因是什么?
测试代码
#include<iostream> using namespace std; int main(){ const int x = 2; cout << "&x: " << &x << ", x: " << x << endl; int *a = &x; *a = 16; cout << "a: " << a << ", *a: " << *a << ", x: " << x << ", &x: " << &x << endl; int* p = a; cout << "p: " << p << ", *p: " << *p << ", x: " << x << ", &x: " << &x << endl; *p = 15; cout << "*p: " << *p << ", x: " << x << ", &x: " << &x << endl; }
编译及运行输出
$ g++ const.cpp -fpermissive const.cpp: In function ‘int main()’: const.cpp:8:15: warning: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive] int *a = &x; ^ $ ./a.out &x: 0x7ffeead2042c, x: 2 a: 0x7ffeead2042c, *a: 16, x: 2, &x: 0x7ffeead2042c p: 0x7ffeead2042c, *p: 16, x: 2, &x: 0x7ffeead2042c *p: 15, x: 2, &x: 0x7ffeead2042c
原因解析
这是编译器的常量折叠优化导致的:
- 因为
x被声明为const int且用字面量2初始化,编译器会将x视为编译期常量。在编译阶段,就把代码中所有直接使用x的地方(比如cout << x)直接替换成字面量2,而不是生成从内存地址读取x值的指令。 - 虽然通过强制转换指针修改了
x对应的内存地址中的值,但cout输出x时,用的是编译期就替换好的2,而非从内存读取最新值,所以就出现了“同地址但值不同”的假象。 - 当去掉
x的const修饰后,编译器不会进行常量折叠优化,每次使用x都会从对应的内存地址读取值,所以修改内存后x的输出会同步变化。
另外要注意:这种通过强制转换修改const变量的行为属于C++标准中的未定义行为,-fpermissive只是让编译器放宽检查允许编译,但程序的行为是不可预测的,实际运行结果可能因编译器、编译选项不同而变化。
内容的提问来源于stack exchange,提问作者nullptrexception
相关产品推荐
相关产品推荐

