为何字符串字面量因char*或char[]声明方式不同存储位置各异?
为什么char*与char[]声明字符串后修改行为存在差异?
先看两段代码的核心区别:
触发段错误的代码:
#include <stdio.h> int main() { char *test = "this is a string"; test[0] = 'q'; printf(test); return 0; }
正常运行的代码:
#include <stdio.h> int main() { char test[] = "this is a string"; test[0] = 'q'; printf(test); return 0; }
具体解释:
char 声明的本质*
"this is a string"是C标准定义的字符串字面量,这类常量会被编译器放置在程序的只读数据段(比如你看到的.rodata),该区域的内存属性是只读的,不允许写入操作。char *test是一个指针变量,它存储的是这个只读字符串字面量的首地址。当执行test[0] = 'q'时,相当于直接尝试修改只读内存中的数据,这违反了内存访问权限,因此触发段错误。
char[] 声明的本质
- 这种写法是用字符串字面量初始化字符数组,编译器会完成两个动作:首先在栈上(如果是局部变量)分配一块足够容纳整个字符串(包括末尾的
'\0')的可写内存,然后把字符串字面量的内容完整复制到这块内存中。 - 你在汇编中看不到原字符串字面量,是因为编译器直接将字符串的字节数据作为初始化值,填充到栈上的数组空间里,而非将字符串单独存入
.rodata再通过指针引用。这块栈内存是可写的,所以test[0] = 'q'的修改操作完全合法,不会触发错误。
- 这种写法是用字符串字面量初始化字符数组,编译器会完成两个动作:首先在栈上(如果是局部变量)分配一块足够容纳整个字符串(包括末尾的
总结差异根源:
char*是指向只读字符串字面量的指针,操作的是只读内存区域;char[]是创建并初始化一个可写的字符数组,操作的是栈上的可写内存区域。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

