Phase #05

配列


1.「配列」はデータのかたまり

この章では「配列」と呼ばれるデータ構造についてみていきます。配列とはおおざっぱに言うと、ある特定の関連性を持ったデータの集まりです。今まで習ってきた言葉で少し難しく言うと、同じ型のデータを連続した領域でまとめて扱っている状態、とでも考えて下さい。これではやはり分かりづらいと思うので例を使って理解してみましょう。
パターン1例えばある地点の気温を数値データとして扱いたいとします。下のようにA地点、B地点の2地点で観測した値をデータとして保持するには2つの変数が必要です。int型で表すとすると次のような感じになるでしょう。

 int tempA, tempB
パターン2ここでA地点とB地点の間の3地点、C〜Eについてもデータが欲しくなりました。同じように変数を宣言すると

 int tempA, tempB, tempC, tempD, tempE

変数が多くなってきました。ちょっと面倒ですね。まだこのくらいなら良いのですが、100とか200とかの単位になるととても大変です。こんな時に配列を使うのです。
上の例ではint型のデータが5つ収まればいいのですよね。そこで、このように宣言するのです。

 int temp[5]

今までの宣言と違って [5] というものがついています。これが配列の宣言なのです。これでint型の変数を5つ宣言したのと同じ分だけ「箱」を確保したことになるわけです。
ちなみにこのような1列のデータを表す配列を1次元配列と呼びます。
パターン3話は戻って次にA-B間と平行した線上のデータも扱いたいとします。宣言はこんな感じになるでしょう。

 int temp1[5], temp2[5], temp3[5]

これもさっきと同じような感じですね。ということはこれも配列で表現できてしまうのでしょうか?答えはイエスです。配列でまとめてしまうと、

 int temp[3] [5]

またまた [3] というものがついています。これで3 X 5 = 15個の変数を宣言したのと同じになるわけです。とても便利ですね。1次元配列と同様で、このような平面的なデータを表す配列を2次元配列と呼びます。
これで配列というものがどんなものかイメージは掴めたと思います。

2.配列の宣言


配列は1つの変数名を使って同じ型の複数のデータを入れておく記憶領域です。この配列につける変数名を「配列名」それぞれのデータを「要素」データの数を「要素数」と呼びます。つまり配列の各要素は同じ型で同じ大きさになります。

A.1次元配列の宣言


 型宣言子 配列名 [要素数]

型宣言子 int,float,charなど全てのデータ型が可能
配列名   識別子と同じ規則
要素数   整数定数
格納領域 各要素は連続した領域に格納


普通の変数の場合複数個宣言をしても連続した領域に確保されませんが、配列ではデータ領域を要素数だけ連続して確保します。
配列の確保のされ方

B.2次元配列の宣言


2次元配列は1次元配列が2つ並んだものとみなせます。

 型宣言子 配列名 [要素数] [要素数]

型宣言子 int,float,charなど全てのデータ型が可能
配列名   識別子と同じ規則
要素数   整数定数
格納領域 各要素は連続した領域に格納


2次元配列
この arry という2次元配列は、3個の要素を持つ配列が2行あることになります。2次元配列も連続的にデータ領域が確保されます。まず、1行目の要素3個分が連続で確保され、続いて2行目の要素分が確保されます。要素数が変わっても同じようになります。

C.3次元以上の配列の宣言


1次元、2次元とできたように3次元、4次元と基本的には何次元でも可能です。(実際にはメモリの大きさなど実行するマシン性能によって限界があります)
要素の並び順は配列要素数の右側にあたる要素から順に並んでいます。

3.配列要素の参照


配列のそれぞれの要素を参照するにはどうするのでしょうか?ここで、「添字」というものを使います。添字配列のそれぞれの要素を表すための数字です。0から始まり、配列の一番最初の要素を表すのは0、次の要素は1というようになっています。
普段何かに番号付けをするときは1からつけることはあっても0からつけることはないですよね?しかし、C言語に限らずコンピュータの世界では0という数字をよく使うのです。これにはアドレスという概念が関係しているのですが、ここでは詳しく述べません。後々出てくるのでちょっと気にしておいてください。
1次元配列の場合は次のようになります。

 配列名 [添字]

配列名   識別子と同じ規則
添字    整数定数もしくは整数型変数
       0 〜(要素数 - 1)

 char string[5] ; /* char型の配列 string の宣言 */
 char char1, char2; /* char型の変数 char1,char2 の宣言 */
添字を使うと参照できる
 char1 = string[0] ; /* 配列の最初の要素の値を変数に代入 */
 char2 = string[4] ; /* 配列の最後の要素の値を変数に代入 */

上の例で一番最後の要素→添字 = 5と間違いやすいので注意して下さい。添字は必ず0〜(要素数 - 1)だということを忘れないようにしましょう。
2次元配列でも基本的には同じように参照できます。

 int data[2] [3] ; /* int型の配列 data の宣言 */
 int val1, val2; /* int型の変数 val1,val2 の宣言 */
2次元配列の添字
 val1 = data[0] [0] ; /* 1行1列目(=最初の要素)の値を変数に代入 */
 val2 = data[1] [2] ; /* 2行3列目(=最後の要素)の値を変数に代入 */
メモリ上の並びと添字の関係

4.配列の初期化


配列を使うプログラムでは実行開始時に一度にデータの代入、つまり初期化をすることがあります。代入は普通の変数と同じような感じでできます。違いは添字を指定することだけです。基本的には普通の変数と変わらないのですから、要素1つ1つに値を代入すれば初期化できます。

 int data[2] ; /* int型の配列の宣言 */
 char string[4] ; /* char型の配列の宣言 */

 data[0] = 1; /* 各要素に値を代入 */
 data[1] = 10;
 data[2] = 100;

 string[0] = 'a'; /* char型の場合は文字を代入 */
 string[1] = 'b';
 string[2] = 'c';
 string[3] = 'd';

このような書き方ではとてもわかりづらく、間違いの原因となります。そこで次のように宣言と同時に初期化するとより分かりやすくなります。

 int data[2] = { 1, 10, 100 }; /* int型の配列の宣言と初期化 */
 char string[4] = { 'a', 'b', 'c', 'd' }; /* char型の配列の宣言と初期化 */

ここで要素数を省略することもできます。コンパイルをするときにコンパイラが要素数を自動的にカウントしてくれます。

 int data[ ] = { 1, 10, 100 }; /* data[3] と同じ */
 char string[ ] = { 'a', 'b', 'c', 'd' }; /* string[4]と同じ */

2次元配列を一度に初期化する場合は、1行目の要素列、2行目の要素列というようにして、各行の要素列を { } で囲んで順に初期化します。

 int data[2] [3] = { { 2, 4, 6 }, { 3, 6, 9 } }; /* 2次元配列を宣言と同時に初期化 */

この場合、配列の行を分かりやすくするために改行してあげるとより分かりやすくなります。

 int data[2] [3] = { { 2, 4, 6 },
             { 3, 6, 9 } }; /* 改行して行別にする */

2次元配列でも要素数を省略できます。ただし、一番右の列を表す添字だけは省略できません。

 int data1[ ] [3] = { { 2, 4, 6 },
             { 3, 6, 9 } }; /* data1[2] [3] と同じ */
 int data2[2] [ ] = { { 2, 4, 6 },
             { 3, 6, 9 } }; /* コンパイルエラーになる */


Jump to Phase #04-3Phase #04-3: 制御文(3) へ
Phase #05-2: 配列(2) へJump to Phase #05-2

△戻る
▲トップに戻る