Why, in C, is a statically declared array name not an lvalue?

Asked

Viewed 110 times

8

Why, in C, the name of a statically declared array is not a lvalue?

A lvalue is an expression that can appear on the left side of an assignment statement. It is an expression that represents a storage place in memory.

It has been said that it is because one cannot change the base address of a array statically declared in memory.

The base address is the initial memory position of a contiguous block allocated/reserved for that array. In the case of static allocation, this block is in the stack or in part "date" (data) from the program’s memory, which is responsible for storing the global variables.

And why, as opposed to that, a struct is a lvalue?

One struct statically declared is also a contiguous block, in the stack or in the data part, composed of the sum of the spaces allocated to its components, to which a name is given.

Where the base address is special that a array cannot be assigned and a struct can?

Why can I assign to a struct other static struct, but to the array statically declared within it I cannot assign another array? I’m missing some basic notion.

  • If statically declared arrays were lvalues there would be two scenarios for implementation: 1) when the array was copied, the program would copy only the memory address - in the same way as pointers - the problem here is that the array would lose its static quality and should be dynamically allocated - in the same way as pointers. Imagine, for example, the case of an array declared within a struct. How struct could reserve memory for this array, if it could be modified at runtime?

  • In the second case, the entire array would be copied - in this scenario, they would be more like structs - but here the implementation difficulties only increase. For how to copy arrays of different sizes? Worse than that, as C doesn’t even know the size of the array at runtime, the program can’t even know which size of the memory block has to be copied. And this difficulty is so absurd that even the implementation of string copy functions is complicated, given the amount of variations of strcpy existing, none of them very practical or good.

  • And why doesn’t that happen with structs? Simple because structs have a well-known fixed length at compile and run time. So they’re as easy to copy as the primitive types.

1 answer

7


Read Arrays are pointers?. This explains the exception for this case. Change the value of a array statically declared would violate the definition of array.

All other cases you have a direct address, so the variable (which is a lvalue) contains a value. You can take any value and assign it to something that already has a value (usually as long as it has compatibility between them, but this compatibility is flexible).

As you’ve probably seen, a array ends up being a pointer to the real value. So if you assign a value to it, it is assigning to the pointer (currently pointing to the first element of the array) or for the real value? It is for the pointer, which by the definition of the language is not a lvalue. See the specification:

Except when it is the operand of the sizeof Operator, the _Alignof Operator, or the unary & Operator, or is a literal string 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.

A pure pointer would not be statically allocated, but in declaring you said that there would be something static. This is not compatible, the language cannot accept.

And you couldn’t even dream of copying the value of one array in another because nothing guarantees that one object would be compatible with another, and will allow to fade the memory or leave dirt, so much so that all copies of array need to be done manually or through ready-made functions such as memcpy() or equivalent, if such a copy is possible (may not be in a protected writing area).

So if arrays do not decay to pointers the assignment you wanted to do could occur normally, because it would only be a sequence of bytes with known size, just as is the struct (has exception) or other scalar types, not counting indirect, and therefore it would be a lvalue. The fact that it is the object directly allows the compiler to know what it is assigning.

That’s not a feature of array in itself, but from the memory address, see that the specification shows this, and we can exemplify with something that is also not valid:

int x = 1;
int *y = malloc(sizeof int);
&x = y;

I put in the Github for future reference.

What are you doing there? Are you saying that x which is a name for a memory address (you’ve read about it on link above) and that the integer value has been placed 1. Then you’re saying that this variable should point to another place in memory which is what’s set in y. You’re not changing the value of the object, but you’re changing the variable. You do not want and cannot do this, the variable was not declared to be modified by code.

The only reason that the array statically declared is prevented from doing what you proposed is that it does exactly this operation, even if you don’t see it because of automatic decay. It only "appears" to be modifiable but is not.

You are trying to change the natural pointer of the variable that was not explicitly declared to be a pointer.

  • "As you’ve probably seen an array ends up being a pointer to the real value". I don’t really remember that, I don’t know if I read it. What I read is that the array (the variable) points to the base address or that actually is this base address and maybe you read something about before this address there was a little header with something, but I may have gotten confused with something that the malloc makes. In time: @Vandersantos comments did not receive upvotes, are they wrong? They seem right to me.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.