直接用数组初始化:
#include <stdio.h>
int main(void) {
char str[] = "abc";
int i = 0;
while (str[i] != '\0') {
printf("%c\n", str[i]);
i++;
}
str[1] = 'd';
return 0;
}
没有问题,正常输出,没有报错。
但是如果用指针初始化:
#include <stdio.h>
int main(void) {
char *str = "abc";
int i = 0;
while (str[i] != '\0') {
printf("%c\n", str[i]);
i++;
}
str[1] = 'd';
return 0;
}
它执行到 str[1] = 'd'
的时候,就会报 segmentation fault,我在网上搜了一下,
都是说通过指针初始化的字符串是个常量,不能改变。感觉这个很坑啊,只是 char str[] = "abc"
和 char *str = "abc";
这样小的区别而已,为什么通过指针初始化的那个就要是常量呢?是 C 语言规定就是这样,还是是可以理解的?
编译器就是这么做的,记住就行了,不必太纠结。

对linux来说,程序加载后内存是分段的。
对于
char *c="abc"
;程序启动时直接加载到了.data段。当你再定义一个char *d="abc"
时,这两个指针公用一块内存。因此你不能随便改这里的内容,它是共享的,只读的。你就理解成编译器共享常量字符串为了省内存吧。
但是对于
char a[]="abc"
;这种定义是在程序执行时,动态在stack段申请的,因此a,b两个指针的地址不一样。就只有你一个人用,而且函数返回后就销毁了。栈上的内存都是可以随便更改的。验证:
结果: