char *s = "0123"和 char s[] = "0123"的区别 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rookiemaster
V2EX    C

char *s = "0123"和 char s[] = "0123"的区别

  •  
  •   rookiemaster 2024-03-29 16:39:15 +08:00 4654 次点击
    这是一个创建于 630 天前的主题,其中的信息可能已经有所发展或是发生改变。

    为什么前者不可以修改,后者可以修改,是因为存储区域的问题吗?

    22 条回复    2024-03-30 22:26:19 +08:00
    huang119412
        1
    huang119412  
       2024-03-29 16:52:39 +08:00   2
    因为 char s[] = "0123",是语法糖。"0123"是常量字符串,不能修改。但是使用字符数组编译器会把"0123"在栈上复制一份,并把首地址赋值给数组名。
    tuwulin365
        2
    tuwulin365  
       2024-03-29 16:52:58 +08:00
    throcean
        4
    throcean  
       2024-03-29 16:54:40 +08:00
    前面在编译的时候就会生成字符串常量在静态常量区(好像是这个区,有点忘了),后者是栈上的一个字符数组
    tzxxxx
        5
    tzxxxx  
       2024-03-29 16:55:37 +08:00
    https://www.gnu.org/software/c-intro-and-ref/manual/html_node/String-Constants.html
    这个链接中说:The string constant is probably stored in a read-only area of memory.
    似乎还没有说字符串常量一定在只读内存中,不清楚什么场景下会出现。
    qq135449773
        6
    qq135449773  
       2024-03-29 16:56:22 +08:00   7
    @tuwulin365 #2

    你不想回答可以不回答,没必要在这里展示你作为 IT 工作者还使用百度这个搞笑的事实。
    leonshaw
        7
    leonshaw  
       2024-03-29 17:03:40 +08:00
    两个都可以修改,一个是指针,一个是数组。
    liuidetmks
        8
    liuidetmks  
       2024-03-29 17:04:43 +08:00   2
    https://godbolt.org/z/T9d38EWTq

    这个网站挺好,我也是在 v 站看到的
    DiamondY
        9
    DiamondY  
       2024-03-29 18:50:16 +08:00
    @tzxxxx #5 单片机会有这样处理方式,字符串直接存在闪存中,cpu 可以通过地址总线读取,但是不能直接进行写入操作
    oIMOo
        10
    oIMOo  
       2024-03-29 18:52:26 +08:00
    @liuidetmks #8 这个网站好哎 不过汇编都还给老师了哈哈哈
    hefish
        11
    hefish  
       2024-03-29 19:04:17 +08:00
    我写 c 的时候,一直是认为一样的,不同写法而已。
    不过那已经是三十年前的事儿了。
    outgoing4443
        12
    outgoing4443  
       2024-03-29 19:06:08 +08:00
    第一种指针 s 指向一个字符串常量"0123",第二种方法定义了一个字符数组 s ,初始化为字符串"0123"
    Nosub
        13
    Nosub  
       2024-03-29 19:58:38 +08:00 via iPhone
    你需要的是一本《 c primer plus 》,更进一步如果你要搞清楚作用域和内存分配的问题,可以看看《征服 c 指针》,少问人,多读书
    MrKrabs
        14
    MrKrabs  
       2024-03-29 21:20:47 +08:00
    一个栈上放指针,一个直接放数据
    lff0305
        15
    lff0305  
       2024-03-30 00:18:28 +08:00
    十多年以前仔细研究过这个 char *s = "0123"。当时用的还是 VC6.
    结果比较有意思(针对 VC6 ,之后的应该改进了)。

    对于 Debug 版,“0123” 会被放到只读数据段里面(好像是叫.rdata). char* s 是个指向这个只读数据段中一小段数据的一个指针。任何对这个数据段的写操作都会引发段错误。

    相应的这避免了两次调用相同的函数,结果不一致的问题。
    比如下面的代码,假设可写,那么会有

    test() {
    char*s = "123";
    printf("%s", s);
    s[1] = 'a';
    }

    test();
    test(); <--- 这里打印出来 1a3 ,和程序的语义不一致。

    有意思的是上面的代码在 Release 版是没有出错的,打印出来两行 123 和 1a3 。
    当时看了下的结果是,
    对于 Debug 版,生成的 exe 有三个段,代码段(可执行),只读数据段(只读),普通数据段(可读可写)。
    而对于 Release 版,连接器把所有三个段捏到一起去了,整个 exe 文件只有一个段,这个段可读可写可执行。

    总之这个问题和系统的段页式内存管理,以及编译器连接器都有关系
    ethusdt
        16
    ethusdt  
       2024-03-30 08:08:31 +08:00 via iPhone
    新手确实要过这一关,一楼解释的就很好。
    jaycelhz
        17
    jaycelhz  
       2024-03-30 09:00:01 +08:00
    我之前也被还有 char **s 和 char *[]s 搞晕
    xuanbg
        18
    xuanbg  
       2024-03-30 09:27:35 +08:00
    指针怎么就不能修改了?
    zooo
        19
    zooo  
       2024-03-30 09:55:02 +08:00
    插个题外话,不喜勿喷

    都 2024 年,C 语言这套古怪遗留语言表达该扔垃圾箱了
    Inn0Vat10n
        20
    Inn0Vat10n  
       2024-03-30 10:10:48 +08:00   1
    @qq135449773 可这个问题,确实百度都能直接找到答案
    wkla
        21
    wkla  
       2024-03-30 11:23:01 +08:00
    C++会提示"const char *" 类型的值不能用于初始化 "char *" 类型的实体。C 不会。
    不过 C 会把这个字符串存只读段里,所以写的话会报段错误。

    我说怎么怪怪的,越看越不对劲。只能说这套该扔就扔吧。
    arloor
        22
    arloor  
       2024-03-30 22:26:19 +08:00 via Android
    //main.cpp
    int a = 0; 全局初始化区
    char *p1; 全局未初始化区
    main()
    {
    int a = 4; 栈,4 也是存在栈上
    char s[] = "abc"; 栈 "abc"也是存在栈上
    char *p2; 栈
    char *p3 = "123456"; 123456\0 在常量区(是在 Data 段上),p3 在栈上。
    static int c =0 ; 全局(静态)初始化为 0,就是放在 BSS 段
    p1 = (char *)malloc(10);
    p2 = (char *)malloc(20);
    malloc 分配得来得 10 和 20 字节的区域就在堆区。因为属于动态申请分配内存空间
    strcpy(p1, "123456"); 123456\0 放在常量区,编译器可能会将它与 p3 所指向的"123456"优化成一个地方。
    }
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2621 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 13:18 PVG 21:18 LAX 05:18 JFK 08:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86