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

发布于 2022-09-01 18:50:56 字数 716 浏览 20 评论 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;
}

没有问题,正常输出,没有报错。

但是如果用指针初始化:

#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 语言规定就是这样,还是是可以理解的?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

白鸥掠海 2022-09-08 18:50:56

编译器就是这么做的,记住就行了,不必太纠结。
对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
无言温柔 2022-09-08 18:50:56

指针初始化时定义了一个指针指向常量地址,而数组初始化时是该数组申请了地址空间用于存储常量字符串的内容。因此,前者不可变,而后者是可变的。

爱冒险 2022-09-08 18:50:56

数组的字符串内存属于, 所以是可读可写;
指针的字符串内存属于代码块, 只可读, 这个地址程序运行后一直存在且不变.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文