开发者社区> 问答> 正文

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

展开
收起
a123456678 2016-06-08 21:02:04 3657 0
5 条回答
写回答
取消 提交回答
  • 编译器就是这么做的,记住就行了,不必太纠结。 对linux来说,程序加载后内存是分段的。 screenshot

    2020-03-19 10:54:31
    赞同 展开评论 打赏
  • 专注物联网

    编译器就是这么做的,记住就行了,不必太纠结。
    对linux来说,程序加载后内存是分段的。
    screenshot

    验证:

    include
    int main(){

    char a[]="abc";
    char b[]="abc";

    char *c="abc";
    char *d="abc";

    printf("%pn", a);
    printf("%pn", b);
    printf("%pn", c);
    printf("%pn", d);
    }
    结果:

    @ ➜ ~ ./a.out
    0x7fff52ac3afc
    0x7fff52ac3af8
    0x10d13cf8a
    0x10d13cf8a


    编译器就是这么做的,记住就行了,不必太纠结。
    对linux来说,程序加载后内存是分段的。
    screenshot

    验证:

    include
    int main(){

    char a[]="abc";
    char b[]="abc";

    char *c="abc";
    char *d="abc";

    printf("%pn", a);
    printf("%pn", b);
    printf("%pn", c);
    printf("%pn", d);
    }
    结果:

    @ ➜ ~ ./a.out
    0x7fff52ac3afc
    0x7fff52ac3af8
    0x10d13cf8a
    0x10d13cf8a

    2019-07-17 19:32:45
    赞同 展开评论 打赏
  • 乐于学习与分析

    编译器就是这么做的,记住就行了,不必太纠结。
    对linux来说,程序加载后内存是分段的。
    screenshot

    验证:

    include
    int main(){

    char a[]="abc";
    char b[]="abc";

    char *c="abc";
    char *d="abc";

    printf("%pn", a);
    printf("%pn", b);
    printf("%pn", c);
    printf("%pn", d);
    }
    结果:

    @ ➜ ~ ./a.out
    0x7fff52ac3afc
    0x7fff52ac3af8
    0x10d13cf8a
    0x10d13cf8a

    2019-07-17 19:32:45
    赞同 展开评论 打赏
  • 软件开发,安全加密

    编译器就是这么做的,记住就行了,不必太纠结。
    对linux来说,程序加载后内存是分段的。
    screenshot

    验证:

    include
    int main(){

    char a[]="abc";
    char b[]="abc";

    char *c="abc";
    char *d="abc";

    printf("%pn", a);
    printf("%pn", b);
    printf("%pn", c);
    printf("%pn", d);
    }
    结果:

    @ ➜ ~ ./a.out
    0x7fff52ac3afc
    0x7fff52ac3af8
    0x10d13cf8a
    0x10d13cf8a

    2019-07-17 19:32:44
    赞同 展开评论 打赏
  • 编译器就是这么做的,记住就行了,不必太纠结。
    对linux来说,程序加载后内存是分段的。
    screenshot

    验证:
    
    #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
    2019-07-17 19:32:44
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载