これが私の見解です:
C言語の開発は、Cの配列型の進化に関する洞察を提供します。
配列の概要を説明します。
Cの前身であるBとBCPLには、次のような明確な配列型がありませんでした。
auto V[10] (B)
or
let V = vec 10 (BCPL)
Vは、メモリの10「ワード」の未使用領域を指すように初期化される(型指定されていない)ポインタであると宣言します。Bは、既に使用され*
、ポインタの参照解除のためにと持っていた[]
、短縮表記を*(V+i)
意味V[i]
だけでC / C ++、今日のように、。ただし、V
は配列ではなく、メモリを指す必要のあるポインタです。これは、DennisRitchieが構造体タイプでBを拡張しようとしたときに問題を引き起こしました。彼は、今日のCのように、配列を構造体の一部にしたいと考えていました。
struct {
int inumber;
char name[14];
};
しかし、ポインタとしての配列のB、BCPLの概念では、これには、構造体内の14バイトのメモリ領域への実行時に初期化name
する必要のあるポインタをフィールドに含める必要があります。初期化/レイアウトの問題は、配列に特別な処理を加えることで最終的に解決されました。コンパイラは、配列を含む式を除いて、データへのポインタを実際にマテリアライズすることなく、構造体やスタックなどの配列の位置を追跡します。この処理により、ほぼすべてのBコードを引き続き実行でき、「配列を見るとポインターに変換される」ルールのソースになります。これは互換性ハックであり、オープンサイズなどの配列を許可するため、非常に便利であることがわかりました。
そして、配列を割り当てることができない理由は次のとおりです。配列はBのポインタであるため、次のように書くことができます。
auto V[10];
V=V+5;
「アレイ」をリベースします。配列変数のベースが左辺値ではなくなったため、これは無意味になりました。したがって、この割り当ては許可されませんでした。これは、宣言された配列に基づいてこれを実行したいくつかのプログラムをキャッチするのに役立ちました。。そして、この概念は固執しました。配列は、C型システムを一流に引用するように設計されたことがないため、ほとんどの場合、使用するとポインターになる特別な獣として扱われました。また、特定の観点から(C配列が失敗したハックであることを無視します)、配列の割り当てを禁止することには意味があります。開いている配列または配列関数パラメーターは、サイズ情報のないポインターとして扱われます。コンパイラーには、それらの配列割り当てを生成するための情報がなく、互換性の理由からポインター割り当てが必要でした。
typedef int vec[3];
void f(vec a, vec b)
{
vec x,y;
a=b;
x=y;
a=x;
x=a;
}
1978年のCの改訂で構造体の割り当てが追加されたとき、これは変わりませんでした(http://cm.bell-labs.com/cm/cs/who/dmr/cchanges.pdf)。レコードはCで異なるタイプでしたが、初期のK&R Cではそれらを割り当てることができませんでした。memcpyを使用してメンバーごとにレコードをコピーする必要があり、関数パラメーターとしてレコードへのポインターのみを渡すことができました。アシグメント(およびパラメーターの受け渡し)は、構造体の生のメモリーのmemcpyとして単純に定義され、既存のコードを壊すことができなかったため、すぐに採用されました。意図しない副作用として、これは暗黙的にある種の配列割り当てを導入しましたが、これは構造内のどこかで発生したため、配列の使用方法に実際に問題を引き起こすことはありませんでした。