はじめに
初心者さん配列は分かったけど、2次元配列って何?



int arr[3][4]; が読めない…
C言語を学んでいると、必ず出てくるのが 多次元配列 です。
特に初心者の頃は、
[][]が増えて急に難しく見える- メモリ上でどう並んでいるのか分からない
- ループとの組み合わせで混乱する
こうなりやすいです。
しかし実際は、
「配列の中に配列が入っている」
と理解すれば、そこまで難しくありません。
この記事では、
- 多次元配列とは何か
- 2次元配列の使い方
- メモリ上の並び方
- for文との組み合わせ
- 関数に渡すときの注意点
- ポインタとの関係
まで、実務目線で分かりやすく解説します。
基本的な配列についてはこちらの記事で解説しています。


この記事はこんな人向け
- 多次元配列がよく分からない
arr[i][j]の意味を理解したい- 2次元配列とfor文の関係を学びたい
- メモリ構造まで理解したい
- 配列とポインタの理解を深めたい
C言語文法解説シリーズ
本記事は「C言語文法解説シリーズ」の1つです。
C言語の文法を、組み込み開発の視点も交えて解説しています。
C言語文法解説シリーズ一覧はこちら


多次元配列とは
多次元配列とは、
「配列の中に配列を持つ配列」
のことです。
例えば次のコード。
int arr[2][3];これは、
2個の配列を持つ配列
↓
各配列の中に int が3個ある
という意味になります。
イメージするとこうです。
arr
├─ [0] → {1個目, 2個目, 3個目}
└─ [1] → {1個目, 2個目, 3個目}
つまり、
行 × 列
のような表形式データを扱えるようになります。



[][] が増えると急に怖くなります…



実は単純で、“配列の中に配列がある”だけなんだ。
表みたいに考えると理解しやすいよ。
2次元配列とは
最もよく使う多次元配列が 2次元配列 です。
宣言方法
int arr[2][3];これは、
2行3列の配列
を意味します。
実際の使用例
#include <stdio.h>
int main() {
int score[2][3] = {
{10, 20, 30},
{40, 50, 60}
};
printf("%d\n", score[0][0]);
printf("%d\n", score[1][2]);
return 0;
}実行結果
10
60
arr[i][j] の意味
score[1][2]これは、
1行目の2列目
ではありません。
C言語では 0から始まる ため、
2行目の3列目
を意味します。
表にするとこうです。


なので、
score[1][2]は 60 になります。
for文との組み合わせ
2次元配列は、
for文と組み合わせて使うことが非常に多いです。
配列全体を表示する
#include <stdio.h>
int main() {
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}実行結果
1 2 3
4 5 6
なぜfor文を二重にするのか
2次元配列は、
行
↓
列
という構造だからです。
つまり、
外側ループ → 行を移動
内側ループ → 列を移動
しています。
イメージ:
[0][0] → [0][1] → [0][2]
↓
[1][0] → [1][1] → [1][2]
C言語のループ処理(for, while)についてはこちらの記事でまとめています。




メモリ上ではどう並んでいるのか
ここがかなり重要です。
2次元配列は、
メモリ上ではバラバラではなく、
連続して並んでいます。
メモリイメージ
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};メモリ上ではこうなります。


つまり、
行ごとに連続して並ぶ
構造です。
これを 行優先(row-major)
と呼びます。
なぜこれが重要なのか
この仕組みを理解すると、
- ポインタ
- 配列アクセス
- DMA
- バッファ処理
- 画像データ
- 行列演算
などの理解につながります。
組み込み開発では特に重要です。
配列とメモリ配置の関係についてはこちらの記事で詳しく解説しています。


多次元配列とポインタ
実は2次元配列は、
内部的にはアドレス計算でアクセスされています。
例えば:
arr[i][j]は内部的には、
*(*(arr + i) + j)として扱われます。



えっ、配列って内部ではポインタなんですか?



“配列そのもの”はポインタじゃないよ。
ただ、配列名は先頭アドレスとして扱われることがあるんだ。
配列とポインタの関係についてはこちらの記事で詳しく解説しています。


関数に渡すときの注意
ここは初心者がかなり詰まりやすいです。
そのまま渡せそうで渡せない
例えば:
void func(int arr[][]) {
}これはエラーになります。
なぜか
C言語は、
1行のサイズ
を知らないと、
アドレス計算できないからです。
正しい書き方
void func(int arr[][3]) {
}または
void func(int (*arr)[3]) {
}です。
なぜ列数は必要なのか
2次元配列はメモリ上で連続しています。
例えば:
1 2 3 4 5 6
ここで、
arr[i][j]を計算するには、
何個飛ばせば次の行か
を知る必要があります。
そのため、
列数(1行のサイズ)
が必要になります。
3次元配列とは
さらに次元を増やすこともできます。
int arr[2][3][4];これは、
2 × 3 × 4
の配列です。
ただし実務では、
- 2次元配列
- 配列+構造体
- 動的確保
で済むことも多く、
3次元以上は頻度が下がります。
多次元配列の実務での使用例
表データ
社員 × 月
画像データ
縦 × 横
RGBなら:
縦 × 横 × 色
ゲームマップ
マップ座標
組み込みのセンサーデータ
センサー番号 × サンプル番号
多次元配列でよくあるミス
① 添字範囲外アクセス
arr[2][3]など。
範囲外アクセスは未定義動作です。
② 行と列を逆にする
arr[row][col]を意識することが重要です。
③ ループ条件ミス
for(i = 0; i <= 2; i++)のようなミス。
<= と < を間違えやすいです。
まとめ
多次元配列とは、
「配列の中に配列を持つ配列」
です。
特に重要なのは:
- 2次元配列は表のように扱える
arr[i][j]でアクセスする- for文を二重にして使う
- メモリ上では連続配置される
- 行優先で並ぶ
- 関数渡しでは列数が必要
という点です。
多次元配列は、
配列・ポインタ・メモリ理解の重要なステップです。
ここを理解すると、
C言語の理解がかなり深まります。
この記事が参考になった方へ
配列を含むC言語の基本文法をこちらの記事で整理しています。


組み込みエンジニアとして技術を学ぶことは重要ですが、
キャリアや副業についても同時に考える必要があります。
副業の現実や市場価値、今後のキャリア戦略については、
こちらの記事でまとめています。


技術に関するご相談・開発・自動化ツール作成・記事執筆などのご依頼も承っています。
小さなご相談からでもお気軽にご連絡ください。









コメント