const变量不能通过直接赋值修改,但可用const_cast强制转换指针后修改栈上变量(未优化时可能生效),而全局/字面量const因常量折叠或只读段保护修改会失败或触发UB。

const变量真的不能修改吗?
能,但不是靠直接赋值。C++标准明确禁止通过常规途径修改const对象,否则行为未定义(UB)。所谓“能改”,本质是绕过编译器的类型检查,用指针强制穿透const限定——前提是该变量本身**未被编译器优化为常量折叠值**,且内存可写。
为什么const_cast有时改不成功?
常见现象:用const_cast去掉const后赋值,运行时没报错,但打印值不变;或程序崩溃;或在不同编译器/优化等级下结果不一致。
- 变量定义为字面量或全局
const整数(如const int x = 42;),GCC/Clang可能将其放入只读段,或直接常量折叠——此时修改会触发段错误(SIGSEGV) - 局部
const变量(如函数内const int y = 100;)通常分配在栈上,内存可写,const_cast后修改一般能生效,但仍是UB -
const引用绑定到非const源时(如int a = 1; const int& r = a;),用const_cast改r实际改的是a,这是安全的
实操:用const_cast修改栈上const变量
仅限调试或极端兼容场景,生产代码禁用。以下代码在无优化(-O0)下通常可运行:
int main() {
const int val = 99;
int* p = const_cast<int*>(&val);
*p = 100; // UB,但x86_64 + -O0 下常能成功
printf("%d\n", val); // 可能输出100,也可能仍是99(编译器缓存)
}关键点:
立即学习“C++免费学习笔记(深入)”;
- 必须取地址再转指针,不能对字面量(如
const_cast<int*>(42))操作 - 若变量声明带
static或定义在全局,更大概率进.rodata段,修改失败 - 开启
-O2后,printf可能仍打印原值——编译器已把val当作不可变常量内联了
比const_cast更危险的“野路子”
有人用reinterpret_cast或联合体(union)绕过const,这些方式问题更大:
-
reinterpret_cast<int*>(const_cast<void*>(&val)):多此一举,不增加安全性,反而降低可读性 - 用
union { const int c; int nc; } u = {.c = 5}; u.nc = 6;:违反严格别名规则(strict aliasing),GCC/Clang在-O2下可能彻底优化掉修改逻辑 - 直接
mprotect改内存页权限:Linux下可行但极度不必要,且Windows无直接等价API
真正需要“运行时可变常量”的场景,应该用std::atomic<T>、mutable成员,或干脆放弃const改用文档约定+访问控制。


















