为何修改C语言只读结构体成员时,两段代码表现不同?
全局与局部const结构体修改行为差异的原因
两段代码的核心区别在于const修饰的结构体变量B的存储位置不同,直接导致了修改操作的不同结果:
第一段代码(全局const结构体)
全局作用域的const变量会被编译器分配到只读数据段(.rodata),这个内存区域被操作系统标记为只读属性。当你用指针int *ptr = &B.a;强制转换并尝试修改*ptr时,本质是对只读内存执行写操作,会触发内存访问错误(比如Linux下的段错误Segmentation fault),因此修改无法成功。
对应的代码:
typedef struct { int a; int b; }A; const A B={ .a = 5, .b = 1, }; int main() { int *ptr = &B.a; *ptr = 12; printf("var = %d\n", B.a); return 0; }
第二段代码(局部const结构体)
定义在main函数内的局部const变量会被分配到栈内存,栈内存本身是可读写的。这里的const只是编译器提供的语法约束——编译时会检查你是否直接修改B.a,但不会给栈上的这个变量设置内存级别的只读属性。当你通过指针强制转换绕过编译检查后,写操作可以直接修改栈内存里的内容,因此printf能输出修改后的值。
对应的代码:
typedef struct { int a; int b; }A; int main() { const A B={ .a = 5, .b = 1, }; int *ptr = &B.a; *ptr = 12; printf("var = %d\n", B.a); return 0; }
需要注意:这种通过指针强制修改const变量的行为属于C语言未定义行为,标准不保证任何运行结果,不同编译器、操作系统甚至编译优化选项都可能让结果不一样,实际开发中绝对不能这么写。
内容的提问来源于stack exchange,提问作者320BIT
相关产品推荐
相关产品推荐

