Is there a reason why an array name is not an lvalue?

家住魔仙堡 提交于 2019-11-27 16:45:38

问题


For example,

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

According to C - A Reference Manual, an array name cannot be an lvalue. Thus, x cannot be an lvalue. But, what is the reason the array name cannot be an lvalue? For example, why does an error occur in the third line?


回答1:


Your reference is incorrect. An array can be an lvalue (but not a modifiable lvalue), and an "array name" (identifier) is always an lvalue.

Take your example:

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) ...

We see that x is a primary expression and is an lvalue, because it has previously been declared as designating an array object.

However, the C language rules state that an array expression in various contexts, including the left-hand-side of an assignment expression, are converted to a pointer which points at the first element of the array and is not an lvalue, even if the array was. Specifically:

Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

(C11 6.3.2.1 paragraph 3).

The pointer which is the result of the conversion specified above is not an lvalue because an lvalue designates an object, and there is no suitable object holding the pointer value; the array object holds the elements of the array, not a pointer to those elements.

The example you use in your question implies that you understand that an array expression decays (is converted to) a pointer value, but I think you are failing to recognize that after the conversion, the pointer value and the array are two different things. The pointer is not an lvalue; the array might be (and in your example, it is). Whether or not arrays are lvalues in fact has no bearing on your example; it is the pointer value that you are trying to assign to.

If you were to ask instead: Why do arrays decay to pointers when they are on the left-hand-side of an assignment operator? - then I suspect that there is no particularly good answer. C just doesn't allow assignment to arrays, historically.




回答2:


Array names are non-modifiable lvalues in C.:)

Arrays are named extents of memory where their elements are placed. So you may not substitute one extent of memory for another extent of memory. Each extent of memory initially allocated for an array declaration has its own unique name. Each array name is bounded with its own extent of memory.




回答3:


It's true that array names yield pointer values in many contexts. But so does the & operator, and you don't expect that to be assignable.

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! */

So when learning the relationship between arrays and pointers, remember that a is usually the same as &a[0] and then you won't think lvalue-ness is an exception to the rule - it follows the rule perfectly.




回答4:


An array is an lvalue, however it is a non-modifiable lvalue.

It most likely has to do with compatibility of types. For example, you can do this:

struct ss {
    char c[10];
};

...

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

But not this:

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


来源:https://stackoverflow.com/questions/39021998/is-there-a-reason-why-an-array-name-is-not-an-lvalue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!