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

时间:2016-08-18 15:23:40

标签: c arrays lvalue

例如,

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

根据C - A Reference Manual,数组名称不能是左值。因此,x不能是左值。但是,数组名称不能是左值的原因是什么?例如,为什么第三行发生错误?

4 个答案:

答案 0 :(得分:3)

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

数组是命名元数据的内存范围。因此,您可能无法将一个内存范围替换为另一个内存范围。最初为数组声明分配的每个内存范围都有自己唯一的名称。每个数组名称都有自己的内存范围。

答案 1 :(得分:2)

您的参考不正确。数组可以是左值(但不是可修改的左值),以及"数组名称" (标识符)总是左值。

举个例子:

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

申请C11 6.5.1,第2段:

  

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

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

但是,C语言规则规定各种上下文中的数组表达式(包括赋值表达式的左侧)将转换为指向数组的第一个元素且不是左值的指针,即使阵列是。具体做法是:

  

除非它是sizeof运算符的操作数,_Alignof运算符,或者   一元& operator,或者是用于初始化数组的字符串文字,一个具有的表达式   类型''数组''转换为类型为''指向类型'指针的表达式   到数组对象的初始元素,而不是左值。如果数组对象有   注册存储类,行为未定义。

(C11 6.3.2.1第3段)。

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

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

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

答案 2 :(得分:1)

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

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]相同,然后您不会认为左值是规则的例外 - 它完全遵循规则。

答案 3 :(得分:0)

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

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

struct ss {
    char c[10];
};

...

struct ss s1 = { { "hello" } };
struct ss s2 = s1;

但不是这样:

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