2次元配列のインデックスはポインタ(アドレス)なのか?配列とメモリ配置の仕組みを解説

C言語関連

C言語やC++などで2次元配列を扱っていると、「配列のインデックスはポインタ(アドレス)なのか?」という疑問を持つことがあります。特に配列名や添字演算子の仕組みを理解すると、メモリ上でデータがどのように管理されているのかが分かりやすくなります。

この記事では、2次元配列のインデックスとポインタの関係、実際のメモリ配置、配列アクセスの仕組みについて、初心者にも分かるように解説します。

2次元配列のインデックスはポインタ(アドレス)ではない

結論から言うと、2次元配列のインデックス自体はポインタやメモリアドレスではありません。インデックスとは、配列の中で何番目の要素を参照するかを表す整数値です。

例えば、以下のような2次元配列を考えます。

int data[3][4];

この場合、data[1][2]の「1」や「2」はインデックスであり、アドレスそのものではありません。「1番目の行の2番目の列」という位置を指定するための番号です。

2次元配列がメモリ上でどのように配置されるか

2次元配列は、見た目では表のように行と列がありますが、コンピューターのメモリ上では基本的に連続した領域として保存されています。

例えば、以下の配列を考えます。

int a[2][3] = {{1,2,3},{4,5,6}};

メモリ上では次のような順番で配置されます。

アドレス
1000番地 1
1004番地 2
1008番地 3
1012番地 4
1016番地 5
1020番地 6

つまり、2次元配列は内部的には1次元的なメモリ領域として管理されています。

配列の添字演算子はポインタ演算に変換される

C言語では、配列の添字アクセスはポインタ演算として考えることができます。

例えば、1次元配列の場合、以下の2つの書き方は同じ意味になります。

a[3]
*(a + 3)

a[3]は「配列aの先頭アドレスから3つ分進んだ場所の値を取得する」という意味になります。

ただし、ここで重要なのは、インデックスの数字である「3」がアドレスになるわけではないという点です。インデックスを利用して、コンパイラが内部的にアドレス計算を行っています。

2次元配列では行単位でポインタとして扱われる

2次元配列の場合は少し複雑になります。例えば、以下の配列があります。

int a[3][4];

この場合、aは「4個のintを持つ配列」を3個持つ2次元配列です。つまり、aの各要素は1行分の配列になります。

そのため、a[1]は2行目全体を指すような形で扱われ、型としては「intへのポインタ」ではなく「int[4]へのポインタ」と考える必要があります。

具体的には、以下のような関係になります。

  • a は1行目の先頭アドレス
  • a[1] は2行目の先頭位置
  • a[1][2] は2行目3列目の値

2次元配列とポインタ配列は別物

初心者が混乱しやすいポイントとして、2次元配列とポインタ配列は似ているようで異なるという点があります。

例えば、以下は2次元配列です。

int a[3][4];

一方、以下はポインタ配列です。

int *a[3];

2次元配列ではデータが連続したメモリに保存されますが、ポインタ配列では各要素が別々の場所を指すことができます。

例えば、文字列を複数管理するときなどではポインタ配列が便利ですが、画像データや行列計算などでは2次元配列がよく使われます。

2次元配列をポインタで扱う場合の注意点

2次元配列を関数へ渡す場合などでは、ポインタの理解が重要になります。

例えば、以下のような関数があります。

void func(int a[][4])

この場合、実際には以下のような意味になります。

void func(int (*a)[4])

つまり、4個のintを持つ配列へのポインタとして渡されています。列数が必要になる理由は、次の要素へ移動するときに何バイト進めばよいか計算する必要があるためです。

例えばint型が4バイトの場合、1行進むには4個分、つまり16バイト移動する必要があります。

まとめ

2次元配列のインデックスはポインタやアドレスではなく、配列内の位置を示す番号です。ただし、C言語では配列アクセスが内部的にポインタ演算として処理されるため、インデックスとアドレスが関係しているように見えます。

2次元配列では、行単位でメモリ上に配置され、配列名や添字を使ったアクセスはコンパイラによってアドレス計算へ変換されます。

「インデックス=アドレス」ではなく、「インデックスを使ってアドレスを計算している」と理解すると、2次元配列とポインタの関係を正しく理解できます。

コメント

タイトルとURLをコピーしました