You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用-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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 05:31:17