字符数组的文字字符串初始值设定项

Posted

技术标签:

【中文标题】字符数组的文字字符串初始值设定项【英文标题】:Literal string initializer for a character array 【发布时间】:2011-01-03 09:54:57 【问题描述】:

数组衰减为指针的情况如下:

出现在表达式中的 T 数组类型的左值 [参见问题 2.5] 衰减(除了三个例外)成指向其第一个元素的指针;结果指针的类型是指向T的指针。

(例外情况是数组是 sizeof 或 & 运算符的操作数,或者是。)

当数组是“字符数组的文字字符串初始化器”时,如何理解这种情况?请举个例子。

谢谢!

【问题讨论】:

相关:Exception to array not decaying into a pointer? 【参考方案1】:

数组不衰减为指针的三个例外情况如下:

例外 1. — 当数组是 sizeof 的操作数时。

int main()

   int a[10];
   printf("%zu", sizeof(a)); /* prints 10 * sizeof(int) */

   int* p = a;
   printf("%zu", sizeof(p)); /* prints sizeof(int*) */

例外 2。 — 当数组是 & 运算符的操作数时。

int main()

    int a[10];
    printf("%p", (void*)(&a)); /* prints the array's address */

    int* p = a;
    printf("%p", (void*)(&p)); /*prints the pointer's address */

例外 3. — 当数组用文字字符串初始化时。

int main()

    char a[] = "Hello world"; /* the literal string is copied into a local array which is destroyed after that array goes out of scope */

    char* p = "Hello world"; /* the literal string is copied in the read-only section of memory (any attempt to modify it is an undefined behavior) */

【讨论】:

在所有编辑之前,我更喜欢您的回答。简明扼要地回答了问题。现在它回答了很多甚至没有被问到的问题。 :-) 谢谢普拉森。一些问题:(1)在异常3中,所以这里的左值“Hello world”是char数组“a”的字符串文字初始化器,因此“Hello world”不会衰减为指针? (2) 异常2中,“&a”是否与数组“a”的第一个元素的地址相同? 答案是(1)是,(2)不是。对于 (2),在大多数计算机上,如果您打印值,它们将打印相同的值(我不知道它们不会在哪里打印)。但是&a 指向整个数组,而&a[0] 指向a 的第一个元素。因此,如果您打印&a + 1&a[0] + 1,即使&a&a[0] 打印相同的值,它们也会有所不同。 是的 &a 的值与数组 'a' 的第一个元素的地址的值相同,但它们的类型不同。 谢谢阿洛克。我认为搅拌文字是右值而不是左值,因为它是只读内存中某些存储的值,而不是存储本身,并且不能出现在 = 的左侧。如果我错了,那么除了字符串文字之外的任何文字也可以是左值吗?那么左值是什么意思,是什么使左值与右值不同?【参考方案2】:

假设声明

char foo[] = "This is a test";
char *bar  = "This is a test";

在这两种情况下,字符串文字“This is a test”的类型都是“15 个字符的数组”。在大多数情况下,数组表达式从类型“T 的 N 元素数组”隐式转换为“指向 T 的指针”,并且表达式的计算结果为数组第一个元素的地址。在bar 的声明中,就是这样。

然而,在foo 的声明中,表达式被用于初始化另一个数组的内容,因此转换为指针类型;相反,字符串文字的内容被复制到foo

【讨论】:

+1 以获得清晰简洁的答案;也许这里唯一表明异常是关于 literal string 而不是分配给它的 char 数组(假设两者都是字符数组)。 "This is a test" 作为字符串初始化器一个数组。作为一个表达式,它不会衰减为一个指针,而是一个数组。很棒。【参考方案3】:

这是字符数组的文字字符串初始值设定项:

char arr[] = "literal string initializer";

也可以是:

char* str = "literal string initializer";

来自 K&R2 的定义:

字符串文字,也称为字符串 常量,是一个字符序列 用双引号括起来,如 “……”。字符串的类型为 ``array of 字符''和存储类静态 (见下文第 A.3 段)并被初始化 与给定的字符。无论 相同的字符串文字是不同的 是实现定义的,并且 程序的行为试图 更改字符串文字是未定义的。

【讨论】:

正如 Prasoon 提到的,这些不是一回事 谢谢,伊莱。那么在这些例子中,什么是字符串字面量初始化器呢?什么是不会衰减为指针的“T 类型数组的左值”?【参考方案4】:

您似乎从 comp.lang.c 常见问题解答中提取了该引用(可能是旧版本或印刷版本;它与在线版本的当前状态不太匹配):

http://c-faq.com/aryptr/aryptrequiv.html

相应部分链接到常见问题解答的其他部分,以详细说明这些例外情况。在你的情况下,你应该看看:

http://c-faq.com/decl/strlitinit.html

【讨论】:

以上是关于字符数组的文字字符串初始值设定项的主要内容,如果未能解决你的问题,请参考以下文章

C中如何实现数组的传值引用

使用格式参数时,Swift 中的字符串初始值设定项问题

为啥这种语法专门用于初始化字符串文字而不能用于字符数组? [复制]

Java中数组初始值设定项中带有尾随逗号的数组

构造函数初始值设定项列表中长度未知的数组

让编译器检查数组初始值设定项的数量