
C言語の基本|2次元配列の初期化
波括弧で行をそろえれば、表データの準備はすっきり完了。2次元配列の初期化を身につけよう。
2次元配列は、行と列を持つ表形式のデータを管理するための仕組みです。学生ごとの点数、店舗ごとの売上、ゲームのマップなど、縦と横の関係を持つデータを整理して保存できます。
配列を宣言しただけでは、関数内に作った各要素は不定値になることがあります。そこで役立つのが、配列の宣言と同時に最初の値を設定する初期化です。
2次元配列では、配列全体を表す波括弧の中へ、各行を表す波括弧を並べます。見た目は少し複雑ですが、表の1行ずつを順番に書いていると考えれば難しくありません。
ここでは、2次元配列を初期化する基本構文、行と列への値の対応、行数を省略できる条件、添字による参照と変更、二重for文による表示方法を順番に解説します。
2次元配列を初期化する
初期化とは、配列を宣言すると同時に最初の値を設定することです。
2次元配列は、次の形で初期化します。
型名 配列名[行数][列数] = {
{0行目の値},
{1行目の値},
{2行目の値}
};1行で表すと、次のような構文になります。
型名 配列名[行数][列数]
= {{値, 値, ...}, {値, 値, ...}, ...};各部分の役割は次のとおりです。
| 部分 | 役割 |
|---|---|
| 型名 | 各要素へ保存するデータの型 |
| 配列名 | 2次元配列の名前 |
| 行数 | 縦方向の要素数 |
| 列数 | 横方向の要素数 |
| 外側の波括弧 | 配列全体 |
| 内側の波括弧 | 1行分の初期値 |
たとえば、3台の装置について朝・昼・夜の消費電力を保存するなら、次のように初期化できます。
int power[3][3] = {
{42, 58, 49},
{38, 61, 45},
{47, 55, 52}
};この配列は、3行3列の9要素を持っています。
初期化子は行ごとに対応する
2次元配列の内側の波括弧は、各行のデータを表します。
int power[3][3] = {
{42, 58, 49}, /* 0行目 */
{38, 61, 45}, /* 1行目 */
{47, 55, 52} /* 2行目 */
};配列の内容を表にすると、次のようになります。
| 装置\時間帯 | 朝・列0 | 昼・列1 | 夜・列2 |
|---|---|---|---|
| 装置1・行0 | 42 | 58 | 49 |
| 装置2・行1 | 38 | 61 | 45 |
| 装置3・行2 | 47 | 55 | 52 |
初期値と要素の対応は次のとおりです。
| 初期値 | 保存される要素 |
|---|---|
| 42 | power[0][0] |
| 58 | power[0][1] |
| 49 | power[0][2] |
| 38 | power[1][0] |
| 61 | power[1][1] |
| 45 | power[1][2] |
| 47 | power[2][0] |
| 55 | power[2][1] |
| 52 | power[2][2] |
内側の波括弧を行ごとに改行すると、どの値がどの行へ入るのかを確認しやすくなります。
図1:二重の波括弧と行・列の対応

この図から分かること
外側の波括弧は2次元配列全体を囲み、内側の波括弧はそれぞれ1行分のデータを表します。
最初の内側の波括弧は0行目、次は1行目、その次は2行目に対応します。それぞれの行の中では、値が列0、列1、列2の順に入ります。
行と列の添字は0から始まる
2次元配列の要素を指定するときは、行と列の2つの添字を使います。
配列名[行の添字][列の添字]C言語の添字は0から始まります。
power[0][0]これは、0行目の0列目、つまり装置1の朝の消費電力42を表します。
power[1][1]こちらは、1行目の1列目、つまり装置2の昼の消費電力61を表します。
人が見る順番と添字の関係は次のようになります。
| 人から見た位置 | 行の添字 | 列の添字 | 要素 |
|---|---|---|---|
| 装置1の朝 | 0 | 0 | power[0][0] |
| 装置1の夜 | 0 | 2 | power[0][2] |
| 装置2の昼 | 1 | 1 | power[1][1] |
| 装置3の朝 | 2 | 0 | power[2][0] |
| 装置3の夜 | 2 | 2 | power[2][2] |
3行3列の配列で利用できる添字は、行、列ともに0から2までです。
初期化した要素を変更する
初期化後も、添字を指定して個別の要素を変更できます。
たとえば、装置2の昼の消費電力を61から64へ変更するなら、次のように書きます。
power[1][1] = 64;変更前と変更後を比較すると、次のようになります。
| 装置\時間帯 | 朝 | 昼 | 夜 |
|---|---|---|---|
| 装置1 | 42 | 58 | 49 |
| 装置2・変更前 | 38 | 61 | 45 |
| 装置2・変更後 | 38 | 64 | 45 |
| 装置3 | 47 | 55 | 52 |
代入する値は、配列の要素型と同じint型として扱われます。
初期化した要素を参照する
配列の値を取り出すときも、行と列の添字を指定します。
printf("%d\n", power[2][0]);power[2][0]には47が入っているため、次のように表示されます。
47計算に使うこともできます。
int total = power[0][0] + power[0][1] + power[0][2];この式では、装置1の朝・昼・夜の値を合計しています。
2次元配列全体を処理する場合は、要素を1個ずつ指定するより、二重for文を使う方法が便利です。
初期化子があれば行数を省略できる
2次元配列では、初期化子が書かれている場合に限り、先頭にある行数を省略できます。
int power[][3] = {
{42, 58, 49},
{38, 61, 45},
{47, 55, 52}
};コンパイラは、内側の波括弧が3組あることから、行数を3と判断します。
そのため、次の2つは同じ大きさの配列になります。
int power[3][3] = {
{42, 58, 49},
{38, 61, 45},
{47, 55, 52}
};
int power[][3] = {
{42, 58, 49},
{38, 61, 45},
{47, 55, 52}
};どちらも3行3列の配列です。
列数は省略できない
2次元配列を初期化するとき、行数は省略できますが、列数は省略できません。
次の書き方は正しくありません。
int power[][] = {
{42, 58, 49},
{38, 61, 45},
{47, 55, 52}
};2次元配列では、1行に何個の要素があるのかが分からないと、次の行が始まる位置を決められません。そのため、列数の指定が必要です。
省略のルールを整理すると、次のようになります。
| 配列 | 初期化子がある場合に省略できる部分 |
|---|---|
| 1次元配列 | 要素数 |
| 2次元配列 | 先頭の行数 |
| 3次元以上の配列 | 最初の次元の要素数 |
多次元配列では、最初の次元だけを省略でき、それより内側の要素数は指定する必要があります。
図2:省略できる行数と省略できない列数

この図から分かること
初期化子があれば、コンパイラは行の数を数えられるため、2次元配列の行数を省略できます。
一方、列数はメモリ上で各行の区切りを判断するために必要です。そのため、2次元配列では列数を省略できません。
初期化した2次元配列を二重for文で処理する
2次元配列は行と列を持つため、全要素を順番に処理するときはfor文を二重にします。
基本形は次のとおりです。
for (行を進める処理) {
for (列を進める処理) {
配列[行][列]を処理する;
}
}3行3列の配列なら、次のように書けます。
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
printf("%d ", power[row][col]);
}
printf("\n");
}外側のfor文は行を進め、内側のfor文は現在の行の列を進めます。
| 外側の変数row | 内側の変数col | 処理する要素 |
|---|---|---|
| 0 | 0、1、2 | power[0][0]~power[0][2] |
| 1 | 0、1、2 | power[1][0]~power[1][2] |
| 2 | 0、1、2 | power[2][0]~power[2][2] |
1行分の処理が終わったあとに改行すると、配列の内容を表のように表示できます。
3台の装置の消費電力を表示する
朝・昼・夜の消費電力を装置ごとに表示するプログラム
ファイル名:10_8_1.c
#include <stdio.h>
int main(void)
{
int power[][3] = {
{42, 58, 49},
{38, 61, 45},
{47, 55, 52}
};
int device;
int period;
printf("3台の装置の消費電力を表示します。\n");
for (device = 0; device < 3; device++) {
printf("装置%d:", device + 1);
for (period = 0; period < 3; period++) {
printf("%dW ", power[device][period]);
}
printf("\n");
}
return 0;
}実行結果の例
3台の装置の消費電力を表示します。
装置1:42W 58W 49W
装置2:38W 61W 45W
装置3:47W 55W 52Wプログラムの内容を詳しく見てみよう
行数を省略した初期化
このプログラムでは、行数を省略して配列を初期化しています。
int power[][3] = {
{42, 58, 49},
{38, 61, 45},
{47, 55, 52}
};列数は3と指定されています。内側の波括弧が3組あるため、コンパイラは行数も3と判断します。
結果として、次の宣言と同じ3行3列の配列になります。
int power[3][3];ただし、この宣言だけでは初期値は設定されません。サンプルでは初期化子を使って9個すべての値を設定しています。
外側のfor文で装置を切り替える
外側のfor文では、処理する装置を順番に切り替えています。
for (device = 0; device < 3; device++) {deviceは0、1、2の順に変化します。
配列の添字にはdeviceをそのまま使用しますが、画面上では装置1から表示したほうが自然です。そのため、表示にはdevice + 1を使っています。
printf("装置%d:", device + 1);内側のfor文で時間帯を切り替える
内側のfor文では、朝・昼・夜に対応する3列を順番に処理します。
for (period = 0; period < 3; period++) {
printf("%dW ", power[device][period]);
}deviceが0の間は、次の3要素が表示されます。
power[0][0]
power[0][1]
power[0][2]その後、deviceが1になり、次の3要素が表示されます。
power[1][0]
power[1][1]
power[1][2]同じ流れで、最後に装置3のデータが表示されます。
改行する位置
改行は、内側のfor文が終了したあとに行います。
printf("\n");この位置に改行を書くことで、1台分の朝・昼・夜が横一列に表示されます。
内側のfor文の中へ改行を書くと、値を1つ表示するたびに次の行へ移ってしまいます。
図3:初期化した配列を二重for文で表示する流れ

この図から分かること
外側のfor文は装置を表す行を進め、内側のfor文は朝・昼・夜を表す列を進めます。
1つの行にある3要素をすべて表示してから改行し、次の行へ移ります。これにより、初期化した2次元配列を表の並びに沿って自然に表示できます。
初期化と代入の違い
初期化と代入は、値を設定するタイミングが異なります。
| 操作 | タイミング | 例 |
|---|---|---|
| 宣言 | 配列を用意する | int power[3][3]; |
| 初期化 | 宣言と同時に値を入れる | int power[3][3] = {{1, 2, 3}, ...}; |
| 代入 | 宣言や初期化のあとで変更する | power[1][1] = 64; |
| 参照 | 保存された値を取り出す | printf("%d", power[1][1]); |
2次元配列全体へ初期値をまとめて設定できるのは、宣言するときです。
宣言後に、次のような形で配列全体をまとめて代入することはできません。
power = {
{42, 58, 49},
{38, 61, 45},
{47, 55, 52}
};宣言後に値を変更するときは、行と列の添字を指定して、各要素へ代入します。
power[0][0] = 42;
power[1][1] = 61;
power[2][2] = 52;2次元配列の初期化で確認したいポイント
| 確認項目 | ポイント |
|---|---|
| 外側の波括弧 | 配列全体を囲む |
| 内側の波括弧 | 1行分の初期値を囲む |
| 初期値の順番 | 行ごとに列0から順番に入る |
| 添字の開始位置 | 行、列ともに0から始まる |
| 省略できる部分 | 初期化子がある場合の行数 |
| 省略できない部分 | 列数 |
| 全要素の処理 | 外側を行、内側を列とする二重for文 |
| 値の変更 | 配列名[行][列]を指定して代入する |
| 値の参照 | 配列名[行][列]で取り出す |
2次元配列の初期化では、内側の波括弧を表の1行として考えることが大切です。行ごとに値をそろえて書けば、コードと表の対応が見やすくなります。
行数を省略するときも、列数は必ず指定します。そのうえで、外側のfor文で行、内側のfor文で列を処理すれば、初期化したすべての要素を順番に扱えるようになります。
