例如,
int x[10];
int i = 0;
x = &i; //error occurs!
根据C - A Reference Manual,数组名称不能是左值。因此,x不能是左值。但是,数组名称不能是左值的原因是什么?例如,为什么第三行发生错误?
答案 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;