
C言語基礎|多次元配列の受渡し
ここまでは、配列を関数に渡す基本(配列+要素数)をやりましたね。
ここから一歩進んで、2次元配列(表)や、さらに上の多次元配列を関数に渡す方法を学びます。
多次元配列は、見た目は「表」ですが、関数に渡すときには 配列の形(行数・列数) がとても大事になります。
特にC言語では、2次元配列を受け取る仮引数には“列数”が必要というルールがあり、ここを押さえると一気にスッキリ理解できます。

今回の例:4人×3科目の「2回分テスト」を合計して表示
- testA:1回目のテスト点
- testB:2回目のテスト点
- total:合計点
サンプルプログラム
プロジェクト名:chap6-18-1 ソースファイル名:chap6-18-1.c
// 4人×3科目のテスト2回分の合計を求めて表示(関数版)
#include <stdio.h>
#define STUDENT 4
#define SUBJECT 3
//--- STUDENT行SUBJECT列の表 a と b の和を out に格納する ---//
void score_add(const int a[STUDENT][SUBJECT], const int b[STUDENT][SUBJECT],
int out[STUDENT][SUBJECT])
{
for (int i = 0; i < STUDENT; i++)
for (int j = 0; j < SUBJECT; j++)
out[i][j] = a[i][j] + b[i][j];
}
//--- STUDENT行SUBJECT列の表 m を表示する ---//
void score_print(const int m[STUDENT][SUBJECT])
{
for (int i = 0; i < STUDENT; i++) {
for (int j = 0; j < SUBJECT; j++)
printf("%4d", m[i][j]);
putchar('\n');
}
}
int main(void)
{
int testA[STUDENT][SUBJECT] = {
{72, 88, 91},
{65, 70, 68},
{90, 77, 84},
{55, 60, 73}
};
int testB[STUDENT][SUBJECT] = {
{80, 85, 89},
{70, 76, 74},
{88, 79, 90},
{60, 66, 71}
};
int total[STUDENT][SUBJECT];
score_add(testA, testB, total);
puts("【1回目のテスト】");
score_print(testA);
puts("【2回目のテスト】");
score_print(testB);
puts("【2回分の合計】");
score_print(total);
return 0;
}図でつかむ:2次元配列は「表」をそのまま渡す
2次元配列は「4人×3科目」の表です。
関数へ渡すと、関数側でも同じ形の表として扱えます。
図:データの流れ(イメージ)

なぜ列数が必要?(多次元配列の受渡しの核心)
2次元配列 m[i][j] を扱うとき、C言語は内部的に
- 「1行が何個の要素でできているか(列数)」
を使って、次の行へ移動する計算をします。
だから、関数側の仮引数は
- 行数は省略できることが多い
- 列数は省略できない(計算できなくなる)
というルールになります。
2次元配列の仮引数で重要なこと
| 観点 | どうなる? | 理由 |
|---|---|---|
| 行数(例:4) | 場合によっては省略可能 | 呼び出し側の配列に合わせて扱えることがある |
| 列数(例:3) | 省略しにくい(基本は必要) | m[i][j] の位置計算に必須 |
※この教材では、分かりやすさ優先で 行数・列数とも固定にしてあります。まずはここから入るのが安心です。
const を付ける意味(安心して渡せる)
今回、
- score_add は a と b を読み取るだけ(書き換えない)
- score_print も読み取るだけ(書き換えない)
- out は結果を書き込む
という役割でした。
const を付ける判断
| 引数 | 中で書き換える? | const を付ける? |
|---|---|---|
| a | いいえ | 付ける |
| b | いいえ | 付ける |
| out | はい | 付けない |
| m(表示用) | いいえ | 付ける |
const を付けておくと、うっかり代入してしまったときにコンパイラが止めてくれるので、安全のガードになります。
使った命令の書式と役割(今回出てきたもの)
登場する命令まとめ
| 命令 | 書式 | 何をする命令? |
|---|---|---|
| #include | #include <stdio.h> | printf / puts / putchar など入出力の宣言を取り込む |
| #define | #define 名前 値 | 定数のように使えるマクロを定義する |
| for | for (初期化; 条件; 更新) 文 | 繰り返し処理を行う(行・列で2重ループ) |
| puts | puts(文字列); | 文字列を表示して改行する |
| printf | printf(書式, …); | 書式付きで表示する |
| putchar | putchar(文字); | 1文字だけ表示する(ここでは改行) |
| return | return 値; | 関数を終了して呼び出し元へ戻る |
演習問題
演習6-12:2回分の点数の「差」を求める関数
4人×3科目の表 a と b について、各要素の差(b - a)を out に入れる関数を作れ。
void score_sub(const int a[4][3], const int b[4][3], int out[4][3]);
解答例
void score_sub(const int a[4][3], const int b[4][3], int out[4][3])
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 3; j++)
out[i][j] = b[i][j] - a[i][j];
}解説
足し算と同じ形で書けます。2重ループで全要素をなめて、差を out に代入するだけです。a と b は読み取りだけなので const 付きが安心です。
演習6-13:指定した学生1人分(1行)の合計を返す関数
4人×3科目の表 t について、指定した学生 row(0〜3)の3科目合計を返す関数を作れ。
int row_sum(const int t[4][3], int row);
解答例
int row_sum(const int t[4][3], int row)
{
if (row < 0 || row >= 4)
return 0;
int sum = 0;
for (int j = 0; j < 3; j++)
sum += t[row][j];
return sum;
}解説
2次元配列は「行を固定して列を回す」書き方ができるのが便利です。範囲外の row が来たときに備えて、最初にチェックしておくと安全です。
