La mia prima ipotesi per la ragione è stata semplicemente a causa delle prestazioni e dei motivi di risparmio di memoria, e anche per la facilità di implementazione del compilatore (specialmente per il tipo di computer nel momento in cui C è stato inventato). Il passaggio di enormi matrici "in base al valore" sembrava avere un impatto enorme nello stack, ha bisogno di un'operazione di copia array completa per ogni chiamata di funzione e probabilmente il compilatore deve essere più intelligente per generare il codice assembly corretto (anche se l'ultimo punto è discutibile) . Sarebbe anche più difficile trattare gli array allocati dinamicamente allo stesso modo degli array allocati staticamente (dal punto di vista della sintassi del linguaggio).
EDIT: dopo aver letto alcune parti da questo link , penso che la vera ragione (e il motivo per cui gli array nelle strutture sono trattati come tipi di valore, mentre i soli array non lo sono) è la compatibilità con le versioni precedenti del predecessore di C B . Ecco la citazione di Dennis Ritchie:
[...} The solution constituted the crucial jump in the evolutionary chain
between typeless BCPL and typed C. It eliminated the materialization
of the pointer in storage, and instead caused the creation of the
pointer when the array name is mentioned in an expression. The rule,
which survives in today's C, is that values of array type are
converted, when they appear in expressions, into pointers to the first
of the objects making up the array.
This invention enabled most existing B code to continue to work,
despite the underlying shift in the language's semantics. [..]