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

为何在C语言中可重新赋值字符串常量指针?修改字符却报错?

字符串指针的赋值与修改差异解析

一、为什么msg = "New string"可以正常执行?

先理清两个关键概念:

  • char *msg是一个指针变量,它本身存放在栈内存中,属于可读写的变量,作用就是保存一块内存的起始地址。
  • "Hello"、"New string"这类字符串字面量,是C语言的字符串常量,编译器会把它们放在程序的只读数据段(.rodata)里——这块内存的内容不允许修改,但它的起始地址可以被读取和传递。

看代码示例1:

char * msg = "Hello";

这行代码是把只读段中"Hello"的首地址,赋值给栈上的指针变量msg。

而msg = "New string";这一步,只是把另一个字符串常量"New string"的首地址,重新写入到指针变量msg中——本质是修改了指针变量自身的值(也就是它指向的目标地址),完全没有触碰只读段里的字符串内容。因为栈上的指针变量本身是可写的,所以这个操作完全合法。

最后printf输出的是msg当前指向的"New string",自然能正常打印。

二、为什么修改字符串字符会触发段错误?

看代码示例2:

char * msg = "Hello";
*(msg + 1) = 'a';

此时msg指向的是只读数据段中"Hello"的首地址,*(msg+1)对应的是这个字符串的第二个字符'e'。当你试图给这个位置赋值'a'时,本质是在向只读内存区域写入数据,这违反了操作系统的内存保护规则,直接触发段错误(Segmentation Fault)。

额外说明:*(msg + 1) = "a";这行代码还有类型不匹配的问题——"a"是const char*类型的指针,而左边*(msg+1)是char类型的变量,编译器通常会给出警告,但运行时依然会因为尝试写入只读内存而触发段错误。

总结

  • 指针变量本身存放在栈上,是可读写的,所以可以重新赋值它指向的地址。
  • 字符串字面量存储在只读数据段,其内容不允许修改,任何写入操作都会触发内存保护错误。
  • 如果需要可修改的字符串,应该用char msg[] = "Hello";(栈上的字符数组)或者通过malloc动态分配堆内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:50:36