C言語基礎|配列の要素と添字

配列って、「同じ型のデータをズラッと並べて持てる」便利な仕組みでしたよね。
でも本当に使いこなすには、もう一歩だけ大事な考え方があります。

それが 要素(element)添字(subscript)

配列は箱の集合で、添字はその箱を指さす番号です。
この2つが分かると、配列の読み書き・ループ処理・バグ回避まで一気にラクになります!

要素とは(配列の中身の正体)

配列の要素は、すべて同一型の変数です。

配列の宣言要素の型要素の数
int a[5];int5個a[0]~a[4] は全部 int
double x[7];double7個x[0]~x[6] は全部 double

つまり「ある要素だけ double、別の要素は int」みたいなことは起きません。
配列は 同じ型の箱が並ぶ、これが基本です。

添字演算子 [] と a[b] の意味

配列の要素にアクセスするのが 添字演算子 [] です。

書き方意味
a[b]配列 a の先頭から b 個後ろの要素をアクセスする。

ここで b は 添字(subscript) と呼ばれて、整数値です。
「先頭から何個後ろ?」を表します。

添字は 0 から始まる(ここが最重要)

要素数 n の配列があったら、存在する要素はこうなります。

  • a[0], a[1], …, a[n - 1] が存在する。
  • a[n] は存在しない。

例:要素数 5 のとき

添字要素
0a[0](先頭)
1a[1]
2a[2]
3a[3]
4a[4](末尾 = 5-1)
5a[5](存在しない)

つい「5個あるから 0~5」って思いがちだけど、0~4 です。

図でつかむ:添字は「先頭からの距離」

配列 a があるとき、添字はこういうイメージです。

つまり a[3] は「先頭から3個後ろの要素」です。

宣言の [] と アクセスの [] は役割が違う

同じ [] でも、意味が違います。

使われ方役割
宣言の []int a[5];要素数を指定するための区切り。
アクセスの []a[i]添字演算子として要素を読み書きする。

見た目は同じでも、宣言アクセスで意味が変わるのがポイントです。

存在しない要素を触るとどうなる?(要注意)

a[-1] や a[n] など、存在しない要素へアクセスしたときの動作は保証されません。
つまり、運が悪いとメモリ破壊や謎のバグになります。

何がまずい?
a[-1]配列より手前のメモリを触る。
a[5](要素数5の場合)配列より先のメモリを触る。
ループ条件が i <= 5最後に i=5 で a[5] を触る危険

配列の基本ルールはこれです。

  • 添字は 0 以上
  • 添字は 要素数 未満(i < 要素数)

サンプルプログラム

やること

  • 6個の整数データを配列に入れる(代入)
  • 添字と値をセットで表示する

プロジェクト名:chap5-2-1 ソースファイル名:chap5-2-1.c

// 6個の気温(整数)を配列に入れて一覧表示
#include <stdio.h>

int main(void)
{
    int temp[6];   // 6個の気温データ
    int i;

    // 先頭から順に値を代入(例として固定値)
    for (i = 0; i < 6; i++) {
        temp[i] = 18 + i;   // 18,19,20,21,22,23
    }

    printf("気温データを表示します。\n");

    for (i = 0; i < 6; i++) {
        printf("%d番目の要素 temp[%d] = %d\n", i, i, temp[i]);
    }

    return 0;
}

実行結果例

気温データを表示します。
0番目の要素 temp[0] = 18
1番目の要素 temp[1] = 19
2番目の要素 temp[2] = 20
3番目の要素 temp[3] = 21
4番目の要素 temp[4] = 22
5番目の要素 temp[5] = 23

このプログラムで出てきた命令の「書式」と「何をするか」

for 文(配列走査の主役)

配列を先頭から順にたどる(走査する)ときに定番です。

書式

for (初期化; 条件式; 更新) {
    繰り返す処理
}

何をする命令?

  • i を 0 から始めて
  • i < 6 の間だけ繰り返し
  • 1回ごとに i を増やす(i++)

だから temp[0]~temp[5] を順番に扱えます。

printf(表示する)

書式

printf(書式文字列, 値1, 値2, ...);

何をする命令?
書式文字列の %d などの場所に値を埋め込んで、画面に出します。

例:

printf("temp[%d] = %d\n", i, temp[i]);
  • 1つ目の %d に i
  • 2つ目の %d に temp[i]

が入ります。

走査(traverse)ってなに?

配列の要素を 先頭から順に一つずつなぞっていくことを走査といいます。

走査のイメージ典型コード
0 → 1 → 2 → … → n-1for (i = 0; i < n; i++)

配列と for 文が相性バツグンなのは、この走査が自然にできるからです。

Type[n] 型ってどう読む?

要素型が Type、要素数が n の配列の型は Type[n] 型 と表します。

宣言型の表現呼び方
int a[5];int[5] 型int の配列
double x[7];double[7] 型double の配列

ここで Type は一般的な型の記号で、Type という型が存在するわけじゃないよ、という注意も覚えておくとスッキリです。

演習問題

演習5-1

要素数 6 の int 配列 data を作り、先頭から順に 10, 20, 30, 40, 50, 60 を代入して表示せよ。

解答例

プロジェクト名:chap5-2-2 ソースファイル名:chap5-2-2.c

#include <stdio.h>

int main(void)
{
    int data[6];
    int i;

    for (i = 0; i < 6; i++) {
        data[i] = (i + 1) * 10;
    }

    for (i = 0; i < 6; i++) {
        printf("data[%d] = %d\n", i, data[i]);
    }

    return 0;
}

演習5-2

要素数 5 の int 配列 rev を作り、先頭から順に 9, 7, 5, 3, 1 を代入して表示せよ。

解答例

プロジェクト名:chap5-2-3 ソースファイル名:chap5-2-3.c

#include <stdio.h>

int main(void)
{
    int rev[5];
    int i;

    for (i = 0; i < 5; i++) {
        rev[i] = 9 - 2 * i;   // 9,7,5,3,1
    }

    for (i = 0; i < 5; i++) {
        printf("rev[%d] = %d\n", i, rev[i]);
    }

    return 0;
}