私が最初に推測した理由は、単にパフォーマンスとメモリ節約の理由と、コンパイラの実装の容易さ(特にCが発明された当時のコンピューターの種類)でした。巨大な配列を「値で」渡すことはスタックに大きな影響を与えるように思われ、関数呼び出しごとに完全な配列コピー操作が必要であり、コンパイラは正しいアセンブリコードを出力するためにより賢くなければなりません(ただし、最後の点は議論の余地があります) 。また、動的に割り当てられた配列を静的に割り当てられた配列と同じ方法で扱うことは、言語の構文の観点からはより困難です。
編集:このリンクからいくつかの部分を読んだ後、本当の理由(および構造体の配列が値型として扱われるのに対し、唯一の配列はそうではない理由)は、Cの先行Bとの後方互換性だと思います。以下はデニスリッチーの引用です。
[...}このソリューションは、型のないBCPLと型付きCの間の進化の連鎖における重要なジャンプを構成しました。ストレージ内のポインターの実体化を排除し、代わりに配列名が式で言及されるとポインターが作成されました。今日のCで生き残っているルールは、配列型の値が式に現れると、配列を構成する最初のオブジェクトへのポインターに変換されるということです。
この発明により、言語のセマンティクスの根本的な変化にもかかわらず、ほとんどの既存のBコードが機能し続けることができました。[..]