プログラミング言語における配列は、同じ種類の複数の値をまとめて格納するためのデータ構造です。たとえば整数の配列、文字列の配列といった具合に要素は同一型であることが期待される場合が多いです。ただし、言語によって振る舞いは異なります。静的型付け言語(C、Javaなど)では配列要素は通常同一型で固定されますが、Pythonのlistのような動的型付け言語では異なる型を混在させることも可能です。配列内の各要素には順番を示す番号が付いており、プログラマはその番号を使って要素を取り出します。この番号を「インデックス」と呼びます。
インデックス(0始まりと1始まり)
多くの言語では最初の要素のインデックスを0として扱います(これを「0始まり」あるいは「0ベース」と呼びます)。C、C++、Java、JavaScript、Pythonなどが典型例です。一方で、最初の要素をインデックス1とする言語も存在します(例:Lua、MATLAB、Fortranなど)。どちらを採用するかは言語設計の方針によりますので、使う言語の仕様を確認してください。
固定長(静的配列)と可変長(動的配列)の違い
固定長配列は宣言時にサイズを決め、その後サイズを変更できない配列です。多くの低レイヤ言語(例:C)の配列はこの方式です。配列のサイズはメモリの割り当てに直結しているため、後から要素数を増やしたい場合は新しい配列を作成して既存の要素をコピーする必要があります(つまり、配列のサイズは直接変更できない)。この点を踏まえ、元の文の「プログラマーが配列を作成する際には、配列のサイズを与えなければなりません。...配列のサイズは変更できないからです。」という説明は、静的配列に対して正しい説明です。
動的配列(例:C++の std::vector、Javaの ArrayList、Pythonの list、Goの slice)は内部で自動的に容量を拡張する機能を持ち、見かけ上はサイズ変更が可能です。内部では新しい大きな領域を確保して要素をコピーする、といった処理を行っています。
メモリ配置とアクセスの仕組み
多くの言語では配列の要素はメモリ上に連続して配置されます(連続メモリ)。このため、インデックスiの要素にアクセスする際は、配列の先頭アドレスに要素サイズを掛け合わせたオフセットを加えるだけで位置が計算でき、ランダムアクセスが高速(O(1))になります。アドレス計算は概ね次の式で表されます:
element_address = base_address + index × sizeof(element)
ただし、言語によっては境界チェック(インデックスが範囲内かどうかの確認)が自動で行われ、範囲外アクセスは例外やエラーになります(例:Java、Python)。一方でCのような言語は通常境界チェックを行わないため、範囲外アクセスは未定義動作を招き、バグやセキュリティ問題になることがあります。
よく使う操作と計算量
- ランダムアクセス(インデックス指定での読み書き):O(1)
- 先頭・中間への挿入・削除:O(n)(要素のシフトが発生するため)
- 末尾への追加:静的配列は不可 / 動的配列は平均O(1)(拡張時はO(n)のコピーが発生)
- 走査(全要素を順に見る):O(n)
多次元配列とジャグ配列
配列は多次元にもできます。多次元配列は行列や表を表現するのに使われます。実装には
- 固定長の多次元配列(連続メモリに行優先・列優先で格納)— Cは行優先(row-major)、Fortranは列優先(column-major)
- ジャグ配列(各行が異なる長さの配列)— JavaやC#でよく見られる
コード例(簡単な例)
Cの固定長配列の例:
int a[5]; // サイズ5の整数配列(固定長) a[0] = 10; // 0番目の要素にアクセス int x = a[3]; // 3番目の要素を読み出す Pythonのリスト(動的配列として振る舞う)例:
a = [1, "hello", 3.14] # 異なる型を混在させることも可能(動的型付け) a.append(42) # 末尾に追加(サイズ自動拡張のように振る舞う) print(a[0]) # インデックスで参照(0始まり) 使いどころと選び方
配列は以下のような場合に適しています:
- 要素への高速なランダムアクセスが必要なとき
- 要素数が事前に判明している、あるいは最大数が決まっているとき(静的配列)
- メモリ局所性を活かして性能を出したいとき(配列は連続配置のためキャッシュ効果が高い)
一方、頻繁に挿入・削除を行う必要がある場合は、リンクリストやツリー、ハッシュ表など別のデータ構造が適切なことがあります。
まとめ
- 配列は同種の複数要素をまとめて扱う基本的なデータ構造。
- インデックスは言語によって0始まりか1始まりかが異なる。
- 静的配列はサイズが固定。サイズ変更は新しい配列を作ってコピーする必要がある。
- 動的配列は見かけ上サイズ変更が可能で内部で再確保とコピーを行う。
- 連続メモリに配置されるためランダムアクセスは高速だが、範囲外アクセスには注意が必要。
C言語での配列の種類はこちら