I know arrays are lvalues and are not assignable but in this case, all the compiler has to do is reassign a pointer. b
should just point to the address of a
. Why isn't this doable?
Because b
isn't a pointer. When you declare and allocate a
and b
, this is what you get:
+---+
| 1 | a[0]
+---+
| 2 | a[1]
+---+
| 3 | a[2]
+---+
...
+---+
| 4 | b[0]
+---+
| 5 | b[1]
+---+
| 6 | b[2]
+---+
No space is set aside for any pointers. There is no pointer object a
or b
separate from the array elements themselves.
C was derived from an earlier language called B, and in B there was a separate pointer to the first element:
+---+
b: | +-+--+
+---+ |
... |
+----+
|
V
+---+
| | b[0]
+---+
| | b[1]
+---+
...
+---+
| | b[N-1]
+---+
When Dennis Ritchie was developing C, he wanted to keep B's array semantics (specifically, a[i] == *(a + i)
), but he didn't want to store that separate pointer anywhere. So instead he created the following rule - unless it is the operand of the sizeof
or unary &
operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T
" will be converted ("decay") to an expression of type "pointer to T
" and the value of the expression will be the address of the first element of the array, and that value is not an lvalue.
This has several practical effects, the most relevant here being that an array expression may not be the target of an assignment. Array expressions lose their "array-ness" under most circumstances, and simply are not treated like other types.
Edit
Actually, that misstates the case - array expression may not be the target of an assignment because an array expression is not a modifiable lvalue. The decay rule doesn't come into play. But the statement "arrays are not treated like other types" still holds.
End Edit
The upshot is that you cannot copy the contents of one array to the other using just the =
operator. You must either use a library function like memcpy
or copy each element individually.