(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";
说:
定义名为char
的m
数组。
使用字符串常量"hello"
初始化数组。这与其他初始化有所不同。有一个从字符串文字中初始化字符数组的规则,该规则从字符串文字中的字符初始化数组元素。
根据字符串文字的大小(包括终止的空字符)设置数组的大小。
最终结果是可以修改的数组m
。char *pm = "hello";
说:
定义指向名为char
的pm
的指针。
使用字符串常量"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
是零,用作空字符。)