Why does C not support direct array assignment?
It is arguably a shortcoming, due to missing features around arrays, but one the original designers choose not to resolve. Add in the (over) emphasis on pointers and pointer arithmetic and keeping track of these things yourself as would be done in assembly.
Arrays in C don't really have sizes. Yes, you can int A[100]; ... sizeof(A) ...
for a declared array, but once A
is used in an expression, its type is immediately converted to pointer to element (here int*
) and the original array's size is lost. This is particularly evident with parameters where an array is passed.
There's not even a convenient built-in for length (e.g. say, lengthof
) that would work for arrays of any element size — instead we have to write something like (sizeof(A)/sizeof(*A))
.
A lot of code in C relies on use of pointers where length is kept by the program using other variables or knowledge rather than having the language keep track.
Often, declaring an array in a struct/union as a last member is secret code for variable length. See for example:
#include <stdio.h>
int A [100];
extern int B [];
struct foo {
int E, F;
int C [];
};
int main()
{
printf("Hello, %ld, %ld, %ld\n", sizeof A, sizeof *B, sizeof (struct foo) );
return 0;
}
I can't say for sure but apparently resolving the short comings only for declared arrays but not for pointers seemed not all that useful. So, some larger built in length mechanism would have been required for general use with pointers.
Still, something could have been done, say by having some syntax that allows the user to specify a number of elements — like A = B[0:n]
or A[0:n] = B
or some other variant — but they simply stopped short of that, leaving it for memcpy
and memmove
. Let's also note that when you choose between memcpy
and memmove
, with the former you're saying that the source and destination do not overlap, whereas with memmove
you're saying they might overlap so backwards copying of the elements may be better than forwards (and it will check at runtime).
So, the various problems:
- pointer oriented rather than array oriented
- no implicit size information on pointers
- aliasing issues
- arrays can be created without even using any array declaration (e.g. using
malloc
), so by their nature they have a length the program has to keep track of on its own
- fixed sized arrays are only useful in narrow contexts
I think punting to the standard library was pretty reasonable here, plus as you note for fixed sized arrays, we can wrap them in a struct/union..