为何通过非const指针修改const static变量会触发段错误?
问题分析:修改const变量的未定义行为与存储位置差异
先贴出你的代码:
#include <stdio.h> int main() { // case 1 const int a = 10; int * ptr1 = &a; *ptr1 = 11; printf("%d\n",*ptr1); // case 2 const static int b = 10; static int * ptr2 = &b; *ptr2 = 11; printf("%d\n",*ptr2); return 0; }
核心前提:修改const变量是未定义行为
首先要明确:C标准规定,通过非const指针修改const限定的变量属于未定义行为——编译器可自由选择处理方式,可能正常运行、崩溃或出现诡异结果,case1能运行只是编译器未触发错误,绝不代表操作合法。
两个case的差异根源:变量存储位置不同
Case1:局部const变量(无static)
局部变量(包括const修饰的)默认存在栈区,栈区是可读写的内存区域。你用int* ptr1 = &a隐式丢弃const属性(GCC会给出警告)后,修改栈内存是允许的,所以程序没崩溃,但这依然违反标准,换编译器或优化等级可能出问题。
Case2:const static变量
static修饰的变量(无论是否const)会存在全局/静态存储区,而const修饰的静态变量,GCC通常会把它放到只读数据段(.rodata)。只读数据段是操作系统标记为不可写的内存区域,当你试图通过指针修改这里的内容时,操作系统会触发内存保护机制,抛出段错误(SIGSEGV),阻止非法写入。
补充:编译器优化的影响
对于const局部变量,编译器可能做常量折叠优化——比如直接把引用a的地方替换成字面量10,但你用指针修改的是栈上的实际存储,所以printf能看到修改后的值;而const static变量在只读段,编译器更可能直接将其当作常量处理,同时内存本身不可写,修改时直接崩溃。
内容的提问来源于stack exchange,提问作者Baranitharan
相关产品推荐
相关产品推荐

