字符数组的字面字符串初始化器

34
以下是当数组衰减为指针时的规则:
一个类型为“T数组”的lvalue[参见问题2.5],如果出现在表达式中(有三个例外),则会衰减为指向其第一个元素的指针;结果指针的类型为“T指针”。
(这些例外包括:当该数组是sizeof或&运算符的操作数,或者是字符数组的文字字符串初始化程序。)
如何理解当数组是“字符数组的文字字符串初始化程序”时的情况?请提供一些示例。
谢谢!

4个回答

56

数组不会退化为指针的三种情况如下:

例外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
我更喜欢你之前的回答,简洁明了并且回答了问题。现在它回答了很多甚至没有被问到的问题。 :-) - Alok Singhal
感谢Prasson。一些问题:(1)在异常3中,因此lvalue“Hello world”是字符数组“a”的字符串文字初始化程序,因此“Hello world”不会衰减为指针吗?(2)在异常2中,“&a”与数组“a”的第一个元素的地址相同吗? - Tim
2
答案是(1)是,(2)不是。对于(2),在大多数计算机上,如果你打印这些值,它们将会打印出相同的结果(我不知道有哪些情况下它们不会)。但是&a指向整个数组,而&a[0]指向a的第一个元素。所以,如果你打印&a + 1&a[0] + 1,它们会是不同的,即使&a&a[0]打印出相同的值。 - Alok Singhal
1
是的,&a 的值与数组 'a' 的第一个元素的地址相同,但它们的类型不同。 - Prasoon Saurav
谢谢Alok。我认为字符串字面值是rvalue而不是lvalue,因为它是只读存储器中某些存储的值,而不是存储本身,并且不能出现在=的左侧。如果我错了,那么除了字符串字面值之外的任何字面值都可以是lvalue吗?那么lvalue是什么意思,什么使lvalue与rvalue不同? - Tim

10
假设有以下声明:
char foo[] = "This is a test";
char *bar  = "This is a test";

在这两种情况下,字符串字面量"This is a test"的类型是"15个字符元素的数组"。在大多数情况下,数组表达式会被隐式转换为类型为"N个元素的T类型数组"的"T类型指针",并且该表达式的值为数组的第一个元素的地址。在bar的声明中,正是这种情况。
然而,在foo的声明中,该表达式被用于初始化另一个数组的内容,因此它不会被转换为指针类型;相反,字符串字面量的内容会被复制到foo中。

1
对于这个明确而简洁的答案要点赞:异常是与字面字符串有关,而不是与它分配给的字符数组有关(考虑到两者都是字符数组)。 - legends2k
1
“这是一个测试”作为字符串初始化程序,一个数组。作为表达式,它不会衰减为指针,而是保持为数组。非常好。 - cdosborn

5
这是一个字符数组的字面值字符串初始化器:
char arr[] = "literal string initializer";

也可以是:

char* str = "literal string initializer";

K&R2 中的定义:

字符串字面值,也称为字符串常量,是由双引号括起来的字符序列,例如“...”。字符串具有“字符数组”类型和静态存储类 (见下面的 Par.A.3),并用给定的字符初始化。相同的字符串字面值是否不同是由实现定义的,而试图修改字符串字面值的程序的行为是未定义的。


4
正如Prasoon所提到的,它们并不是同一件事。 - BlueRaja - Danny Pflughoeft
谢谢,Eli。在这些例子中,什么是字符串字面值的初始化器?"An lvalue of type array-of-T" 是指不会衰减为指针的 T 类型数组对象。 - Tim

2

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