This question already has answers here:
What is the difference between char s[] and char *s?
                                
                                    (13个回答)
                                
                        
                                2年前关闭。
            
                    
char m[] = "hello";

char *pm = "hello";

为什么* pm无法修改?

我看到有人说:
char指针是地址的副本,
char数组是内容的副本,即“ hello”。

我的问题是这样的:


为什么char m[] = "hello";是内容的副本。
m本身也是数组的第一个地址,为什么常量字符串“ hello”将它们分配给不同的效果?
char m[] = {'h','e','l','l','0'};char m[] = "hello"的语法糖吗?

最佳答案

char m[] = "hello";说:


定义名为charm数组。
使用字符串常量"hello"初始化数组。这与其他初始化有所不同。有一个从字符串文字中初始化字符数组的规则,该规则从字符串文字中的字符初始化数组元素。
根据字符串文字的大小(包括终止的空字符)设置数组的大小。
最终结果是可以修改的数组m


char *pm = "hello";说:


定义指向名为charpm的指针。
使用字符串常量"hello"初始化指针。由于不是正在初始化的字符数组,因此不适用于字符数组的规则。相反,"hello"是一个表达式。由于字符串文字本身就是数组,因此适用将数组转换为指针的规则。因此"hello"被转换为指向其第一个字符的指针。然后,将pm初始化为该指针的值。
最终结果是pm指向字符串文字的数组,您不能对其进行修改。


关于您的问题:


  m本身也是数组的第一个地址,为什么常量字符串“ hello”将它们分配给不同的效果?


首先,数组的名称不是数组第一个元素的地址。在许多情况下,它实际上是那样的,但是存在差异。在表达式中使用数组时,它将自动转换为指向其第一个元素的指针,但如果它是sizeof或一元&的操作数,则不会。 (同样,如果它是用于初始化数组的字符串文字,则也不是。)因此,在sizeof m中,m不是指向其第一个元素的指针。它是整个数组,而sizeof m产生整个数组的大小,而不是指针的大小。

其次,由于使用字符串文字初始化数组的规则,使用"hello"作为初始化程序会有不同的效果。具体来说,该规则在C 2018 6.7.9 14中表示:


  字符类型数组可以由字符串文字或UTF-8字符串文字初始化,并可选地用大括号括起来。字符串文字的连续字节(如果有空间或数组大小未知,则包括终止空字符)将初始化数组的元素。


第三,在这些定义中未分配字符串文字。它用于初始化对象。分配和初始化不同,并且具有不同的规则。分配是表达式,其行为与其他表达式非常相似。初始化是声明的一部分,并且具有一些赋值所没有的特殊语法和语义。这就是为什么某些源代码的初始化行为与赋值行为不同的原因。

关于这个问题:


  char m[] = {'h','e','l','l','0'};char m[] = "hello";的语法糖吗


相反。我们可以说char m[] = "hello";是更甜的版本,而char m[] = {'h','e','l','l','o',0};是原始版本。但是,是的,它们具有相同的效果。 (请注意,我纠正了两个错误:列表中应该有一个'o',最后一个元素应该是0,而不是'0''0'是数字零的字符,而0是零,用作空字符。)

10-05 21:02
查看更多