
C言語基礎|多次元配列
1次元配列は「同じ型のデータを横一列に並べたもの」でしたよね。
じゃあ、その配列をさらに並べたら?――そう、配列の配列になります。これが 多次元配列です。
- 2次元配列:行と列で表せる(表・マス目)
- 3次元配列:2次元配列がさらに積み重なる(ページ・回数・層)
- それ以上:理屈は同じ(ただし使いどころは慎重に)
ここでは「2次元配列の考え方」と「C言語での並び方(メモリの連続配置)」を、図と表でしっかり固めます。

多次元配列って結局なに?
多次元配列は、ひとことで言うとこうです。
多次元配列は、配列を要素とする配列である。
1次元配列との違いを並べると分かりやすいです。
| 種類 | 例 | 要素の型 | イメージ |
|---|---|---|---|
| 1次元配列 | int a[3]; | int | 1列に並ぶ |
| 2次元配列 | int m[4][3]; | int[3] | 4行×3列の表 |
| 3次元配列 | int t[15][4][3]; | int[4][3] | 15枚の表(回数×行×列) |
ポイントは 2次元配列の要素は1次元配列、ってところです。
2次元配列ができるまで(派生の考え方)
2次元配列は、2段階でできると考えるとスッキリします。
| 段階 | 何をまとめる? | できる型 |
|---|---|---|
| a → b | int を 3個まとめる | int[3] |
| b → c | int[3] を 4個まとめる | int[4][3] |
図のイメージ
C言語の2次元配列宣言は、右から読むクセをつけると楽です。

宣言の読み方:int a[4][3]; は「4行3列」
| 宣言 | 行数(先頭側) | 列数(末尾側) | 表のサイズ |
|---|---|---|---|
| int a[4][3]; | 4 | 3 | 4行3列 |
| int a[3][4]; | 3 | 4 | 3行4列 |
アクセス方法:a[i][j] は [ ] を2回使う
2次元配列の「1マス」を触るには、添字演算子を連続で使います。
a[i][j]
- a[i] で「i行目(1次元配列)」を選ぶ
- その中の [j] で「j列目(int)」を選ぶ
構成要素(いちばん小さい要素=int)まで分解すると、
4行3列なら 4×3 = 12個の構成要素があります。
メモリ上の並び:末尾側の添字が先に増える(超重要)
2次元配列は「表っぽい」見た目ですが、メモリ上では 一直線に連続して並びます。
しかも並び順はこうです。
末尾側の添字(列)が 0,1,2… と先に増えてから、先頭側(行)が増える
int a[4][3] の並びイメージ
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] ... a[3][2]
つまり、a[0][2] の次が a[1][0] になるのが保証されます。
この並びを「行優先(row-major)」と呼ぶこともあります。
サンプルプログラム
ここでは 3人分の7日間の歩数を 2次元配列で持ち、人ごとの合計と曜日ごとの合計を出すプログラムを例に解説します。
プロジェクト名:chap5-9-1 ソースファイル名:chap5-9-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
// 3人×7日間の歩数データを集計して表示
#include <stdio.h>
#define PEOPLE 3
#define DAYS 7
int main(void)
{
int steps[PEOPLE][DAYS] = {
{8021, 7560, 9102, 10034, 6780, 12010, 8450},
{6500, 7200, 7001, 6900, 8800, 9100, 5000},
{11000, 10500, 9800, 10200, 9700, 9900, 10100}
};
int person_sum[PEOPLE] = {0};
int day_sum[DAYS] = {0};
// 集計(2重ループで全構成要素を走査)
for (int i = 0; i < PEOPLE; i++) {
for (int j = 0; j < DAYS; j++) {
person_sum[i] += steps[i][j];
day_sum[j] += steps[i][j];
}
}
puts("=== 3人×7日間の歩数一覧 ===");
for (int i = 0; i < PEOPLE; i++) {
printf("Person %d:", i + 1);
for (int j = 0; j < DAYS; j++)
printf(" %5d", steps[i][j]);
putchar('\n');
}
puts("\n--- 人ごとの合計 ---");
for (int i = 0; i < PEOPLE; i++)
printf("Person %d total = %d\n", i + 1, person_sum[i]);
puts("\n--- 曜日ごとの合計 ---");
for (int j = 0; j < DAYS; j++)
printf("Day %d total = %d\n", j + 1, day_sum[j]);
return 0;
}この例の気持ちいいところは、steps[i][j] を1回読むだけで、2種類の集計(人・曜日)が同時に進むことです。
2重ループに慣れると、表データの処理が一気に得意になります。
行と列に「意味」を割り当てる
2次元配列は、行と列に役割を持たせると一気に読みやすくなります。
| 添字 | 何を表す? | 例 |
|---|---|---|
| i(行) | 人(Person) | i=2 は3人目 |
| j(列) | 日(Day) | j=5 は6日目 |
steps[i][j]
i = person index (row)
j = day index (column)
3次元配列への拡張イメージ(回数が増えたら)
もし「7日間」を「12週間」や「15回測定」に増やしたら、
2次元を何枚も持つより、3次元にまとめたくなります。
例:
- 15回分の「3人×7日」の歩数
→ int steps[15][3][7];
アクセスは steps[k][i][j] のように [ ] が3回になります。
登場する命令・演算子の書式と役割
配列宣言(2次元)
書式
型 配列名[行数][列数];何をする?
「列数の1次元配列」を行数個まとめて、2次元配列を作ります。
初期化(2次元)
書式
型 配列名[行数][列数] = { { ... }, { ... }, ... };何をする?
行ごとに { } を分けて初期化できます(見た目が表っぽくなって読みやすいです)。
for 文(2重ループ)
書式
for (i = 0; i < 行数; i++) {
for (j = 0; j < 列数; j++) {
処理;
}
}何をする?
表の全マス(全構成要素)を順番に走査して処理します。
puts / printf / putchar
- puts(文字列); は1行表示(改行つき)
- printf(書式, 値...); は整形表示
- putchar('\n'); は改行など1文字出力
演習問題
演習5-10
3行4列の2次元配列をキーボードから読み込み、同じ形で表示せよ。
解答例
プロジェクト名:chap5-9-2 ソースファイル名:chap5-9-2.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int main(void)
{
int a[3][4];
puts("3行4列の整数を入力してください:");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("a[%d][%d]:", i, j);
scanf("%d", &a[i][j]);
}
}
puts("\n入力された表:");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
printf("%4d", a[i][j]);
putchar('\n');
}
return 0;
}解説
2次元配列の基本は 読み込みも表示も2重ループ。
まずは「全マスをなぞる」感覚を身体で覚えるのが狙いです。
演習5-11
4人×3科目の点数を読み込み、学生ごとの合計点だけを表示せよ。
解答例
プロジェクト名:chap5-9-3 ソースファイル名:chap5-9-3.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
#define STU 4
#define SUB 3
int main(void)
{
int score[STU][SUB];
int sum[STU] = {0};
puts("4人×3科目の点数を入力してください:");
for (int i = 0; i < STU; i++) {
printf("Student %d:\n", i + 1);
for (int j = 0; j < SUB; j++) {
printf(" Subject %d:", j + 1);
scanf("%d", &score[i][j]);
sum[i] += score[i][j];
}
}
puts("\n--- 学生ごとの合計点 ---");
for (int i = 0; i < STU; i++)
printf("Student %d total = %d\n", i + 1, sum[i]);
return 0;
}解説
「表(学生×科目)」から、行方向(学生方向)に足し込む練習です。
2次元配列を使う理由が一気にハッキリします。
演習5-12
2回分の点数(回×学生×科目)を3次元配列に読み込み、回ごとの学生合計点を表示せよ。
解答例
プロジェクト名:chap5-9-4 ソースファイル名:chap5-9-4.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
#define TIMES 2
#define STU 3
#define SUB 2
int main(void)
{
int score[TIMES][STU][SUB];
int sum[TIMES][STU] = {0};
puts("2回分の点数を入力してください(3人×2科目):");
for (int t = 0; t < TIMES; t++) {
printf("\nRound %d\n", t + 1);
for (int i = 0; i < STU; i++) {
printf(" Student %d:\n", i + 1);
for (int j = 0; j < SUB; j++) {
printf(" Subject %d:", j + 1);
scanf("%d", &score[t][i][j]);
sum[t][i] += score[t][i][j];
}
}
}
puts("\n--- 回ごとの学生合計点 ---");
for (int t = 0; t < TIMES; t++) {
printf("Round %d:\n", t + 1);
for (int i = 0; i < STU; i++)
printf(" Student %d total = %d\n", i + 1, sum[t][i]);
}
return 0;
}解説
3次元配列も怖くないです。
添字が1つ増えただけで、やってることは同じ。
- t:回
- i:学生(行)
- j:科目(列)
for が1段増えるだけ、という感覚を掴めると勝ちです。
