首页 > C 语言字符串用数组和指针初始化为什么会有这样的区别?

C 语言字符串用数组和指针初始化为什么会有这样的区别?

直接用数组初始化:

#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两个指针的地址不一样。就只有你一个人用,而且函数返回后就销毁了。栈上的内存都是可以随便更改的。

验证:

#include<stdio.h>
int main(){
    char a[]="abc";
    char b[]="abc";
    
    char *c="abc";
    char *d="abc";
    
    printf("%p\n", a);
    printf("%p\n", b);
    printf("%p\n", c);
    printf("%p\n", d);
}

结果:

@ ➜  ~  ./a.out
0x7fff52ac3afc
0x7fff52ac3af8
0x10d13cf8a
0x10d13cf8a
【热门文章】
【热门文章】