数组名称不是左值的原因是什么?

例如,

int x[10]; int i = 0; x = &i; //error occurs! 

根据C – A参考手册 ,数组名称不能是左值。 因此,x不能是左值。 但是,数组名称不能是左值的原因是什么? 例如,为什么第三行会发生错误?

您的参考不正确。 数组可以是左值(但不是可修改的左值),“数组名称”(标识符) 始终是左值。

举个例子:

 int x[10]; int i = 0; x = &i; //error occurs! 

适用C11 6.5.1,第2段:

标识符是主表达式,前提是它已被声明为指定一个对象(在这种情况下它是一个左值)…

我们看到x是一个主表达式并且是一个左值,因为它之前已被声明为指定一个数组对象。

但是,C语言规则声明各种上下文中的数组表达式(包括赋值表达式的左侧)将转换为指向数组的第一个元素且不是左值的指针,即使arrays是。 特别:

除非它是sizeof运算符,_Alignof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则具有类型”数组类型”的表达式将转换为表达式输入”指向类型’的指针,指向数组对象的初始元素,而不是左值。 如果数组对象具有寄存器存储类,则行为未定义。

(C11 6.3.2.1第3段)。

作为上面指定的转换结果的指针不是左值,因为左值指定了一个对象,并且没有合适的对象保存指针值; 数组对象包含数组的元素,而不是指向这些元素的指针。

您在问题中使用的示例意味着您了解数组表达式衰减(转换为)指针值,但我认为您无法识别转换后,指针值和数组是两个不同的东西。 指针不是左值; 数组可能是(在你的例子中,它是)。 数组是否是左值实际上与你的例子没有关系; 它是您尝试分配的指针值。

如果你要问: 当数组位于赋值运算符的左侧时,为什么数组会衰减为指针? – 然后我怀疑没有特别好的答案。 从历史上看,C只是不允许赋值给数组。

数组名称是C中不可修改的左值。:)

数组被命名为内存的范围,其中放置了元素。 因此,您可能无法将一个内存范围替换为另一个内存范围。 最初为数组声明分配的每个内存范围都有自己唯一的名称。 每个数组名称都以其自己的内存范围为界。

确实,数组名称在许多上下文中产生指针值。 但是&运算符也是如此,并且您不希望它是可分配的。

 int i = 42; int *j = malloc(sizeof *j); &i = j; /* obviously wrong */ int a[] = {1,2,3}; &a[0] = j; /* also obviously wrong */ a = j; /* same as the previous line! */ 

因此,在学习数组和指针之间的关系时,请记住a通常与&a[0] ,然后你不会认为lvalue-ness是规则的一个例外 – 它完全遵循规则。

数组左值,但它是一个不可修改的左值。

它很可能与类型的兼容性有关。 例如,您可以这样做:

 struct ss { char c[10]; }; ... struct ss s1 = { { "hello" } }; struct ss s2 = s1; 

但不是这个:

 char s1[10] = "hello"; char s2[10] = s1;