配列
配列とは,同じデータ型の値の集合のためのデータ構造である.第2回において学習した文字列は,文字型の値を集合であった.ここではより一般的な配列について学習する.さらに,添字を拡張した多次元配列についても学習する.
1次元配列
宣言方法
C言語では,配列はその要素数とともに宣言するという決まりがある.以下の例は,int型の要素6個からなる配列scoreを宣言する例である.
int score[6];
このように宣言された配列は,メモリ上の連続した領域に確保される.処理が進み,不要になった段階で確保されていた領域は自動的に解放される.
|
変数の有効範囲を抜けた段階 |
添字による各要素へのアクセス
配列の各要素には,以下のように大かっこを使った添字によってアクセスする.添字として有効なのは,整数定数および整数式である.浮動小数点数は使えない.
score[1] = 83;
printf("%d\n", score[2]);
score[2*i + 1] = 100;
初期化方法
配列を宣言しただけでは,各要素の値は不定である.プログラム開発において,不定値をそのままにしておくことは思わぬバグの混入を招くリスクが高いため,通常は宣言の直後に初期化を行うことが強く推奨される.初期化の典型的なパターンをリスト 1に示す.
int data[10];
int i;
for (i = 0; i < 10 /* 配列の要素数 */; ++i) {
data[i] = 0;
}
また,宣言と初期化を同時に行う方法(リスト 2)も許されている.この場合,要素数を省略することも可能である.特に,固定文字列の初期化などに有用である.
double val[4] = {0.3, -5.1, 102.55, 0.0};
int data[] = {8, -1, 7, 10, 255, -512, 1}; // 要素数を省略する場合
char name[] = "Takushoku Taro";
多次元配列
配列の添字は,多次元に拡張することができる.これによって,例えば2次元データなどに,x, yなどといった座標を添字として用いてアクセスすることが可能となる.多次元に拡張されるのは添字のみであり,データそのものが確保されるメモリ上では常に1次元のアドレスが割り当てられることに注意.
2次元配列の例をリスト 3に示す.
int data[2][3]; // 2行3列の2次元配列を宣言,添字の有効範囲はdata[0-1][0-2]
int rows = 2; // 行数(縦の要素数)
int cols = 3; // 列数 (横の要素数)
int i, j;
// 初期化
for (i = 0; i < rows; ++i) {
for (j = 0; j < cols; ++j) {
data[i][j] = 0;
}
}
// 各行の先頭アドレスを表示
for (i = 0; i < rows; ++i) {
printf("%x\n", &data[i][0]);
}
// 各行の先頭アドレスを表示(省略形)
for (i = 0; i < rows; ++i) {
printf("%x\n", data[i]);
}
// (x,y) = (2,1)の要素に値を代入
data[1][2] = 100;
2次元配列においても,宣言と同時に初期化を行うことが可能である.
int score[3][5] = {
{70, 80, 50, 99, 60},
{60, 45, 70, 88, 30},
{90, 85, 70, 57, 85}
};
リスト 4で初期化された2次元配列を図示したものが図 1である.図の上段は,各要素に対する2次元の添字を示したものである.同じ色の添字は同じ色の次元に対応する.また,図の下段は,この2次元配列のメモリ上に占める領域の概念図である.各行の先頭アドレスの書き方およびその省略形が示されている.
次のリストは,この2次元配列scoreの行ごとの要素の合計値を求めるプログラムの例である.
// 配列score[3][5]は定義されていると仮定
int i, j;
int row_sum[3]; // 行ごとの合計値を格納するための配列
// 初期化
for (i = 0; i < 3; ++i) {
sum[i] = 0;
}
for (i = 0; i < 3; ++i) {
for (j = 0; j < 5; ++j) {
sum[i] += score[i][j];
}
}