Why does the assignment operation of an array not exist, but the assignment of the structure is done in C?

int a[10]; int b[10]; a = b; // illegal typedef struct { int real; int imag; } complex; complex c,d; c = d; //legal 

[I understand that a and b are addresses in the first case, but characters in the second case]

+7
source share
7 answers

For historical information, this may be interesting: http://cm.bell-labs.com/who/dmr/chist.html

In B, an array declaration will allocate memory for the array, as does C, but the name specified for this variable was used to define the pointer to the array. Ritchie changed this to C, so the name "is" an array, but can be used when pointing to a pointer:

The rule that C currently holds is that array type values ​​are converted, when they appear in expressions, to pointers to the first of the objects that make up the array.

This invention allowed most existing B codes to continue working, despite a major shift in the semantics of the language. Several programs that have assigned new values ​​to the array name to adjust its origin - possible in B and BCPL, meaningless in C-are easily repaired.

If at this very early stage Richie defined a = b to copy the array, then the code that he was trying to move from B to C would not be as easily restored. As he defined this, this code will give an error, and he can fix it. If he made C a copy of the array, he would silently change the meaning of the code to copy the array, and not reuse the name used to access the array.

There is another question: β€œWhy this feature has not been added in 40 years since then,” but I think why it was not there from the very beginning. It would be an implementation effort, and that effort would actually make this earlier version of C worse, meaning it’s a little harder to port the B and BCPL code to C. So, of course, Ritchie didn’t.

+6
source

Since C says you cannot, he says: "The modifiable value of lvalue is an lvalue value that does not have an array type, does not have an incomplete type," so the array cannot be assigned.

Also, when you use the name of an array in the context of a value, for example a = b; , both names a and b mean &a[0] and &b[0] . Often referred to as an array "decaying" to a pointer.

However, arrays are not pointers, so trying to assign an array using pointers does not make sense.

+4
source

The main reason is, of course, the Standard. When restricting an assignment operator, it says:

(C99, 6.5.16p2) "The assignment operator must have a modifiable value lvalue as its left operand"

where it defines mutable lvalue as

(C99, 6.3.2.1p1) "The modifiable value of lvalue is a value of l that does not have an array type, [...]".

So assignment of arrays is not allowed.

But the main reasons are the historical reasons of the time when a copy of the array was considered unsuitable for hardware (old PDP systems). Not that also in the first versions of C the assignment of objects of the structure type was also not allowed. It was later added to the language, but for an array, many parts of the language would need to be changed so that arrays could be assigned.

+3
source

The first thing to understand is that arrays are not pointers. Read section 6 of the comp.lang.c FAQ . I'll wait.

...

Well done? No, go back and read it all.

...

Excellent thank you.

Generally speaking, arrays in C are second-class citizens. There are array types, array objects, and even array values, but arrays are almost always controlled by pointers to their elements.

It takes a little more work for the programmer (as you saw, you can't just assign arrays), but it also gives you more flexibility. Programs that deal with arrays usually need to deal with arrays of different sizes, even sizes that cannot be determined before runtime. Even if array assignment is allowed, an array of 10 int and an array of 20 int have different and incompatible types. If you have an array of a fixed size, as in the code in your question, it is common only for some of the elements that are currently relevant; you may have a 10 element array, but currently you are only using the first 5 elements. Processing such an element by element simplifies the processing of only those elements that are currently active (something that you must track yourself).

For a structure, on the other hand, the number and types of members are determined when determining the type. You cannot traverse the members of a structure by advancing a pointer, as with an array, since members usually have different types. Arrays and structures are two different things, and they have different sets of operations that make sense to them.

There are several rules in the language that simplify this, namely:

  • In most, but not all contexts, an array expression is implicitly converted to a pointer to the first element of the array. The exception is:
    • When an array expression is an operand of the & (address) operator,
    • When is the operand sizeof ; and
    • When it is a string literal in the initializer, used to initialize the array object.)
  • The declared array parameter, as in int func(char s[]); , configurable by pointer parameter: int func(char *s); .

(It can be argued that these rules cause more confusion than they prevent, but how language is defined.)

Now I assume that the language could be defined or can be redefined, so that the assignment of the array is allowed in cases where this makes sense:

 int a[10]; int b[10]; /* ... */ a = b; /* Why not? */. 

Perhaps such a change could even be made without breaking existing code. But this will require another special case for the rule of converting an array to a pointer. And this would only be useful in the case of fixed-size arrays, such as a and b , which, although they are quite common in introductory programming exercises, are not so common in production code.

+3
source

The name of the array is a pointer to const, so you cannot change what it points to.

Assuming you meant that c = d in the last line is legal, it simply copies the non-constant variable to another non-constant variable, which is completely legal.

-one
source

a is actually a "pointer" to the first element of the array and is a constant "pointer", so you are trying to assign an l- "pointer".

you can achieve what you are trying to do:

 struct arraystruct { int t[10]; }; struct arraystruct a,b; a=b; 

EDIT: I forgot to mention that there are a few exceptions when an array should not be considered a pointer:

-you can use sizeof (array), but you cannot use sizeof (pointer)

-array literal string

-a and & a are the same

-one
source

This is because the type of array you are using is the so-called static array, i.e. the memory for it is on the stack. If you use dynamic arrays (with pointers), your assignment will be legal (but a memory leak will be possible). It will be a shallow copy.

See also Static array versus dynamic array in C ++

-2
source

All Articles