使用字符串字面量初始化字符数组时,数组表达式不会转换为指针。

3

来自《C语言概述》:

在大多数情况下,编译器会隐式地将数组类型的表达式(如数组的名称)转换为指向该数组第一个元素的指针。

只有在以下情况下,数组表达式才不会被转换为指针:

• 当数组是 sizeof 运算符的操作数时

• 当数组是 & 地址运算符的操作数时

当使用字符串字面值初始化 char、wchar_t、char16_t 或 char32_t 数组时

  1. 请您用一些正负例子解释最后一个条目的含义?我在书中没有找到最后一个条目的例子。
  2. 为什么只是字符型数组而不是其他类型的元素?
1. 正例:
```c char str[] = "Hello"; // 使用字符串字面值初始化字符数组 ```
负例:
```c int arr[5] = {1, 2, 3, 4, 5}; // 不会被隐式地转换为指向 arr[0] 的指针 ```
2. 这是因为 C 语言中字符串实际上是以 null 结尾的字符数组。使用字符串字面值初始化字符数组时,编译器会自动在末尾添加一个 null 字符,以表示字符串的结束。因此,这种情况下将字符串字面值隐式转换为指向第一个字符的指针是很有用的。

1
尝试编译char *str = "hello";char *str = {'h','e','l','l',o','\0'};的区别。 - David Ranieri
@KeineLust 谢谢。str 的类型是指向字符的指针类型,而不是数组类型。引用讨论了一个数组。 - Tim
哎呀,我看错了问题:仅在以下情况下,数组表达式才不会转换为指针: - David Ranieri
2个回答

2
char *ptr = "Hello OP!!";

ptr是指向存储在RODATA段中的字符串字面值的第一个字符的指针。当您进行解引用时,由于字符串字面值是常量字符数组,因此只能读取而不能写入值。

char arr[] = "Hello OP!! How are you my friend?";

在这种情况下:
  1. 为长度为大小文字的数组arr分配空间,包括尾随零。
  2. 将字符串字面量复制到为arr数组分配的空间中
在这种情况下,arr被用作内存中复制字符串字面量的位置。
您可以读取和写入arr元素就像读取和写入一样
现在回答问题
  • 如果所有数组元素的大小,则数组的大小为字节大小。如果将数组转换为指针,则大小将是指针的大小,在这种情况下显然是错误的
  • 数组仅是容纳其所有元素的连续空间。因此,数组的地址始终是该内存位置的地址
  • 我已经解释了第三种情况
您可以查看代码 https://godbolt.org/g/xVL5cR **注意TIM** 字符串字面量不会转换为任何内容。字符串字面量仅作为带有NUL(而不是NULL)终止符的char(wchar_t ....)数组存储在RO内存中。

在《C语言大全》中:“在char *pStr =“Hello,world!”中,字符串字面值表示其第一个元素的地址,就像数组名一样。” - Tim
这正是我所写的 - 字符串字面值是一堆以空字符结尾的字符。由于字符串字面值是只读的,它被存储在 RODATA 段中(如果硬件支持)。这个赋值 char *x = "abcd"; 将 x 赋予了字符串字面值存储位置中字符 'a' 的地址。 - 0___________
我所编辑的是为了澄清第三种情况中,“数组表达式未转换为指针”是什么意思,当数组表达式是字符串字面值时。 - Tim
如果您不喜欢它,我会将其删除。 - 0___________
很遗憾,无法删除它。 - 0___________

1

为什么字符数组而不是其他元素类型?

这是因为字符串字面值具有静态存储期,因此在程序的生命周期内存在于内存中。

尝试修改字符串字面值(使用指向字面值的指针)会导致未定义的行为:它们可能存储在只读存储器中(如.rodata),也可能与其他字符串字面值组合。

任何其他常量都不像这样存储,所以只有字符数组(字面值)。

您能用一些正负例子解释最后一个要点吗?我在书中没有找到最后一个要点的例子。

字符串字面值初始化如下:

char ptr[] = "Hello world!";     // This is char[]
char ptr[] = L"Hello world!";    // This is wchar_t[]
char ptr[] = u8"Hello world!";   // This is char[]
char ptr[] = u"Hello world!";    // This is char16_t[]
char ptr[] = U"Hello world!";    // This is char32_t[]

这个字符串字面量从静态存储区复制到自动存储区,可以对它进行修改。

char ptr[] = {'H','e','l','l',o',' ','w','o','r','l','d','\0'};

它不会是字符串文字,也不会有静态持续存储


你的字符串初始化示例并没有解决提问者的问题,反而让人感到困惑。在这种情况下,字符串字面值实际上被转换为指针。我认为你想要使用 char s[] = "Hello world!"; 这样的方式。这将创建一个字符数组 s,而不是一个指针。 - Gene
谢谢。在最后一个例子中,你如何展示ptr这个“数组表达式将被转换为指针”的情况? - Tim
还有其他类型的字面量,例如(int[]){1, 2, 3} - M.M
char ptr[] = U"Hello world!"; 是错误的,数组的类型必须与初始化器匹配,例如 char32_t ptr[] = U"Hello world!";。其他行也是如此。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接