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

C语言字符数组与字符指针操作差异及栈执行机制问询

C语言两种字符串声明的运行差异解释

复现代码

可正常运行的代码

char c1[] = "hello";
c1[0] = c1[1];
printf("%s\n", c1);

编译正常但运行崩溃的代码

char * c2="hello";
c2[0] = c2[1];
printf("%s\n", c2);

底层执行&栈内存变化说明

数组声明char c1[] = "hello"的执行逻辑

  • 程序加载时,字符串字面量"hello"会被存储在进程地址空间的只读数据段(.rodata),该区域内存被操作系统标记为不可写入。
  • 声明c1数组时,会在当前函数的栈帧上开辟长度为6字节的连续内存(刚好存储hello\0共6个字符),然后将只读数据段中"hello"的内容完整拷贝到栈上的这块内存中。
  • 数组名c1本质是栈上这块可写内存的首地址,修改c1[0]就是操作栈上的可写内存,属于合法操作,程序可正常执行,最终输出eello。

指针声明char *c2 = "hello"的执行逻辑

  • 同样,"hello"本身还是存储在只读数据段中。
  • 声明c2指针时,只会在当前函数的栈帧上开辟一个指针大小的内存(32位系统占4字节,64位系统占8字节),这个指针变量里存储的直接是只读数据段中"hello"的首地址,不会发生内容拷贝。
  • 当你执行c2[0] = c2[1]时,本质是尝试往只读数据段的内存地址写入数据,这会触发操作系统的内存保护机制,抛出段错误(SIGSEGV),程序直接崩溃。

为什么崩溃的代码能正常编译?

C标准中字符串字面量的静态类型是char[N],出于历史兼容原因没有强制限定为const char[N],所以编译器默认不会对这种赋值报错,仅在开启-Wwrite-strings等警告选项时才会提示风险。但操作系统的内存保护是运行时生效的,和编译阶段无关。

内容的提问来源于stack exchange,提问作者MAK1647

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:24:01