Is there a reason why an array name is not an lvalue?
例如,
1 2 3
| int x[10];
int i = 0;
x = &i; //error occurs! |
根据C-A参考手册,数组名不能是左值。因此,x不能是左值。但是,数组名不能是左值的原因是什么?例如,为什么第三行出现错误?
- 它是左值的用例是什么?这是不合理的。这是一个名字。你不能改变名字……
- @ EugeneSh。我不认为这就是OP的意思,但让我们看看……请澄清,你不是说你想动态地改变名字,是吗?
- 如果您不想让它作为一个指针(唯一有意义的含义),那么一旦您更改数组的指针,就会对您已经静态分配的这10个元素缓冲区发出呜呜声。
- @ EugeneSh。如果它是左值,因为数组名被转换为指向int的指针类型,我认为数组名可以用作指针变量!
- @Jin,那么一旦你修改了分配的空间会发生什么呢?如果要将其用作指针,请将其分配给指针变量并使用它。没有理由让它变得有价值。
- 你的问题和你的例子不匹配。即使数组是可修改的左值,您的示例也会为它分配一个指针。数组不是指针;这是类型不匹配。为什么您希望能够将指针值赋给数组?"数组名可以用作指针变量"-no。数组值在某些上下文中衰减为指针。数组不是指针。
- @据我所知,数组类型表达式被转换为指针类型表达式。所以,这不是类型不匹配!
- @davmac-数组不衰减的情况列表远短于它衰减的情况(仅当sizeof或一元&的操作数时)。
- @jin在某些上下文中,数组转换为非左值的指针值(c99/c11 6.3.2.1第3段)。转换后它怎么可能是左值?没有指针对象,只有指针值。左值指定对象。你明白左值是什么吗?
- @奥利弗卡尔斯沃思的确如此,但这在这里真的很重要吗?
- @达马克-回应你的第一条评论。根据规范的引用,x是操作代码段中的指针类型。
- @davmac oh so x只是一个不指定对象的指针类型值?所以我想这就是为什么它不是可修改的左值?
- @Jin-yup,就是这样(和我在vlad答案下面的评论中给出的例子一样)。
- @奥利弗卡尔斯沃思哦,我明白了!谢谢!
- @jin no.x指定一个数组。它只会在使用它的上下文(以及许多其他上下文)中衰减为指针值。衰减会导致一个非左值指针值,该值不会存储在任何对象中。由x指定的数组和它衰减到的指针值是两个不同的值。x是一个左值(虽然不是可修改的左值;显然您的书是错误的),但指针不是。
- @davmac综上所述,x本身是一个指定对象的数组类型,而表达式x是一个不指定对象的指针值?
- @jin no.x是指定数组的表达式。当用作较大表达式的一部分时,数组值(通常)将转换为指针。你试图用不正确的术语解释它。
- @我认为x有两个含义。x既是指定数组对象的表达式,又是计算数组第一个元素地址的表达式!看看这个。stackoverflow.com/questions/17687429/…阅读第一个答案中有关表达式定义的部分!
- 简而言之:不能增加数组。x++;是什么意思?它应该做什么?您不能分配给数组:x = val;应该做什么?[或:x+x或x+a;-]
- @我不同意,x是一个指定数组的表达式。根据C116.5.1,第2段:标识符是主表达式,前提是它已声明为指定对象(在这种情况下,它是左值)。再清楚不过了。它只在转换后成为指针。
- @davmac根据您的答案,我猜第三行的表达式x转换为指针类型,而表达式x是指定数组对象的主表达式?
- @金佑说的好像有两个不同的x表达式,但在第三行只有一个。是的,它是一个主表达式和一个指定数组对象的左值。是的,在计算包含表达式的过程中,该左值被转换为指针。
- @最后一句话让一切都很清楚!"…评估期间"
- 谢谢!!
Array names are non-modificable lvalues in c.:
Arrays are named extents of memory where their elements are placed.所以你不能代替记忆的一个延伸来代替记忆的另一个延伸。一个阵列宣言的每个初始存储器扩展都有其独特的名称。每一个阵列名称都与它自己的存储器扩展相连。
- 但数组类型表达式是否转换为指针类型表达式?例如,在我的代码的第三行中,由于x是一个数组表达式,所以应该将其转换为指针类型表达式。因此,x不再是内存的名称区,而是指针类型。
- 金-当然。但你同样不能写(例如)int x = 1; int y = 2; &x = &y;。
- @这是否意味着指针类型表达式不能是左值?
你的参考资料不正确。一个阵列可以是一个LVALUE(但不是一个可更改的LVALUE),而一个"阵列名称"(标识符)总是一个LVALUE。
以你的例子:
1 2 3
| int x[10];
int i = 0;
x = &i; //error occurs! |
Apply C11 6.5.1,paragraph 2:
An identifier is a primary expression, provided it has been declared
as designating an object (in which case it is an lvalue) ...
我们认为,x是一个基本的表达形式,是一个LVALUE,因为它已经被预先宣布为一个阵列对象。
然而,C语言规定,在各种情况下,包括在分配表达式的左手侧的阵列表达式,被转换成在阵列的第一元素中的点,而不是LVALUE,即使阵列是这样。Specifically:
BLCK1/
(C11 6.3.2.1第3段)。
由于LVALUE设定了一个物体,所以上述特定转换结果的指针不是LVALUE,因此没有一个方便的物体固定指针值;阵列物体固定了阵列中的元素,而不是对这些元素的指针。
例如,在你的问题中,你使用的是一个阵列表达式衰减(被转换为)一个指针值,但我认为,你准确地承认,在转换之后,指针值和阵列是两个不同的东西。指针不是一个LVALUE;该阵列可能是(在你的例子中,它是)。在实例中,无论是LVALUES是LVALUES还是不LVALUES,都没有改变;这是指针值,你试图指定。
如果你要问:为什么当他们在分配操作员的左手边时,阵列会消失?-然后我怀疑没有特别好的答案c/Just doesn't allow assignment to arrays,historically.
事实上,在许多情况下,阵列名称是有效的指针值。但是操作员,你不指望这是可以指定的。
1 2 3 4 5 6 7
| 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]一样,然后你不认为LVAULUE-NESS是规则的一个例外——它是完美的规则。
一个阵列是一个LVALUE,但它是一个不可改变的LVALUE。
它最喜欢与类型兼容。例如,你可以这样做:
1 2 3 4 5 6 7 8
| struct ss {
char c[10];
};
...
struct ss s1 = { {"hello" } };
struct ss s2 = s1; |
但不是这个
ZZU1
- 我不认为这是关于兼容性的问题,而是标准显式地调用了"可修改左值是没有数组类型的左值…"。
- 不,数组不是lvalue 6.3.2.1/3:除非它是sizeof运算符、alignof运算符或一元运算符的操作数,或者是用于初始化数组的字符串文字,否则具有"类型数组"类型的表达式将转换为具有指向初始el的"指向类型指针"类型的表达式。数组对象的元素,不是左值。
- @Jean Baptisteyun&232;s您的报价没有显示您的要求。在某些上下文中,表达式(可能是左值)被转换为不是左值的表达式。这并不意味着原始表达式不是左值。
- @当数组转换为"指向类型的指针"时,引用的是Jean-BaptisteYun&232;。在这种情况下,数组不是左值,但在不转换时仍然是。
- 抱歉,伙计们,但再次阅读这个句子,这对我来说意味着数组不是左值。什么时候有失踪的吗?
- @第6.3.2.2节中的jean-baptisteyun&232;s:"除非它是sizeof运算符、alignof运算符、unary&;运算符、++运算符、--运算符或的左操作数的操作数。运算符或赋值运算符,没有数组类型的左值将转换为存储在指定对象中的值",同样在6.3.1.1中:"可修改的左值是没有数组类型的左值…"。这些短语表明数组是左值,但不是可修改的左值。
- @Jean-BaptisteYun&232;s的"丢失时"不丢失:"除非它是操作数…"。另外,正如我在前面的注释中所说的,这句话说(在大多数情况下)数组值被转换为另一个值(不是左值),它并没有说数组不是以左值开头的。
- @Jean-Baptisteyun&232;s例如6.3.1.8讨论了常见的算术转换。如果我有一个int a和一个float b,我把它们加在一起,就像在a + b中一样,那么"如果任一操作数的对应实类型是float,则另一个操作数将在不改变类型域的情况下转换为其对应实类型是float的类型"——因此a将转换为float。但是你不会因为这个而争辩说int是float,对吧?a仍然是int,尽管在这种情况下,它的值将转换为float。数组到指针的转换也是一样的。
- 由于不是英语母语,我现在理解我对6.3.2.1的误解。谢谢大家的评论,这真的对我有帮助。@davmac:数组的左值(不可修改)转换为非左值的指针类型。