5人分のテストの点数を記録してください、と言われたらどう書きますか。
int score1 = 60, score2 = 85, score3 = 40, score4 = 90, score5 = 75;5人ならまだ我慢できます。では40人のクラスは。1000人の模試は。合計を出すのに score1 + score2 + ... と1000個並べるのは現実的ではありません。同じ型のデータをまとめて扱う道具が必要です。それが配列です。
int score[5]; // int の箱が5個、一列に並ぶ[5] は「箱の個数」を表します。並んだ箱の1つずつを要素と呼び、何番目かを指定して読み書きします。
#include <stdio.h>
int main(void)
{
int score[5];
score[0] = 60;
score[1] = 85;
score[2] = 40;
score[3] = 90;
score[4] = 75;
printf("%d\n", score[0]); // 60
printf("%d\n", score[2] + 10); // 50
return 0;
}角カッコの中の数字を添字(インデックス)と呼びます。先頭は0番です。int score[5] なら使える添字は 0・1・2・3・4 の5つで、score[5] は存在しません。ここは次のトピックでじっくり扱います。
配列があると何が変わるか
変数を5個並べる書き方では、3人目の点数を取り出すのに score3 と名前で指定するしかありません。名前は実行中に変えられないので、「i番目の人」という書き方ができないのです。ここが決定的な違いです。配列なら score[i] と書けて、i を1つずつ増やせば全員ぶんの処理が数行で済みます。ループと組み合わせられること——これが配列の最大の価値です。
大きさは最初に決める
Cの配列は宣言した時点で大きさが決まり、あとから伸び縮みしません。40人のクラス用に int score[40]; と作ったら、41人目は入りません。不便に見えますが、「どこに何個ぶん置くか」を最初に確定できるから速い、という利点の裏返しです。実行してみるまで必要な数が分からない場合の対処法は、第2部の動的確保で扱います。
要素はメモリの上で隣り合って並ぶ
配列の要素は、メモリ上ですきまなく連続して置かれます。これが配列の本質で、あとで学ぶ「添字での高速アクセス」も「関数への渡り方」も、すべてこの性質から説明できます。全体の大きさは sizeof で確認できます。
#include <stdio.h>
int main(void)
{
int a[5];
printf("%zu\n", sizeof(a)); // 20(int 4バイト × 5個)
printf("%zu\n", sizeof(a[0])); // 4
printf("%zu\n", sizeof(a) / sizeof(a[0])); // 5 ← 要素数
return 0;
}罠・注意
- 宣言の
[5]は「個数」、使うときの[0]は「番号」。同じ角カッコでも意味が違います。 - 個数の指定にはコンパイル時に決まる値を使います。初学のうちは
int a[5];のように数字を直接書くか、#define N 5で名前を付けるのが確実です。 - 要素の型は全部同じです。int の配列に文字列は入りません。バラバラの型をまとめたいときは第3部の構造体を使います。
- 宣言しただけの配列の中身は不定です。初期化については t08-05 で扱います。
配列の名前は scores names のように複数形にすると、「これは複数のデータだ」と一目で伝わります。個数を表す変数は n や count が定番です。
まとめ: 配列は「同じ型の箱を一列に並べたもの」。型 名前[個数]; で作り、名前[番号] で出し入れします。