C言語の配列の書き方

512, 2022-07-06

目次

C言語の配列の書き方

C言語では配列を使うことができます。
この配列の書き方について解説します。

結論から言うとC言語の配列は↓のように書きます。

#include <stdio.h>

int main(void) {
    int ary[] = {1, 2, 3};

    printf("%d\n", ary[0]);  // 1
    printf("%d\n", ary[1]);  // 2
    printf("%d\n", ary[2]);  // 3

    return 0;
}

具体的に見ていきたいと思います。

関連記事

C言語の配列とは?

C言語の配列とはどういうものなのでしょうか?
たとえば複数の変数があったとします。
その複数の変数を1つにまとめると便利な場合があります。

そういう時は配列を使うと複数の変数をまとめることができます。

配列は要素というもので構成されています。
配列には複数の要素があります。

各要素はメモリ上で連続しています。
この要素がメモリ上で連続しているというのが配列の特徴です。
たとえばリストなどはメモリが連続していない場合があります。

配列の要素には添え字でアクセスします。
C言語では配列に角カッコをつけて中に整数を書くと添え字アクセスになります。

ary[1];

C言語の配列の宣言、定義方法

C言語の配列は↓のように宣言します。

型 配列名[要素数];

これはコードにすると例えば↓のようになります。

int ary[3];

↑の配列aryはint型の要素を3つ持った配列になります。
各要素は初期化されていません。
ですので要素の値は未定義になります。

あるいは配列の要素を初期化する場合は↓のように定義します。

型 配列名[要素数] = 初期化子リスト;
型 配列名[] = 初期化子リスト;

これはコードにすると↓のようになります。

int ary_a[3] = {1, 2, 3};
int ary_b[] = {1, 2, 3};

↑のary_aary_bはどちらも要素数が3の配列です。
配列を初期化子リスト({1, 2, 3})で初期化する場合は要素数を省略することもできます。
↑の配列はどちらも各要素は先頭から1, 2, 3で初期化されていきます。

配列に使える型

配列に使える型はintだけではなくcharやlongなども使えます。

int main(void) {
    int iary[3];
    char cary[10];
    long lary[20];
    return 0;
}

たとえば配列の型をcharにした場合は配列の1つの要素のサイズ(バイト数)は1バイトになります。
つまりchar型の配列に要素が100個あれば100バイトの配列になるわけですね。

int型のサイズは環境依存ですが4バイトであることが多いです。
ですのでint型の配列で要素数が100あれば4 * 100で400バイトになります。

このように配列のサイズは型と要素数によって決まります。

配列の添え字アクセス

配列に角カッコをつけて整数を書くと配列の要素に添え字アクセスできます。

#include <stdio.h>

int main(void) {
    int ary[] = {1, 2, 3};

    printf("%d\n", ary[0]);  // 1
    printf("%d\n", ary[1]);  // 2
    printf("%d\n", ary[2]);  // 3

    return 0;
}

↑の場合、配列はaryです。これはint型の要素を3つ持つ配列です。
配列の要素は{1, 2, 3}初期化子で初期化されています。

ary[0]と書くと配列の0番目の要素つまり整数1を取得できます。
ary[1であれば配列の1番目の要素つまり整数2です。
こう言う感じで配列の添え字は0から始まります。

範囲外の添え字アクセス

配列の要素数の範囲外の添え字で配列にアクセスするとエラーになる場合があります。
ここがC言語の怖いところなのですがこのエラーは検知できる場合と検知できない場合があります。

エラーが表面化してプログラムがクラッシュする場合もありますし、エラーが表面化せずにプログラムが走り続ける場合もあります。
こういった境界線のエラーを検出したい場合はメモリチェックツールを使いましょう。

たとえばLinux系ではValgrindという有名なメモリチェックツールが使えます。

(^ _ ^)

C言語こわい

(・ v ・)

もっとあげるよ

配列をfor文で回す

配列をfor文で回す場合は↓のようにコードを書きます。

#include <stdio.h>

int main(void) {
    int ary[] = {1, 2, 3, 4};

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

    return 0;
}

↑のコードを実行すると↓の結果になります。

1
2
3
4

配列をfor文で回すにはこのようにカウント変数(i)を使った添え字アクセスが一般的です。
配列の要素数がわかっている場合はその要素数だけfor文を回せば各要素にアクセスできる添え字が手に入ります。

配列の要素数を求める

配列の要素数を求めたい場合はsizeof演算子が使えます。
↓のように使います。

配列の要素数 = sizeof 配列 / sizeof 配列[0];

sizeof 配列で配列全体のバイト数が求まります。
sizeof 配列[0]では配列の要素1つ分のバイト数が求まります。

コードにすると↓のようになります。

#include <stdio.h>

int main(void) {
    int ary[] = {1, 2, 3, 4};
    int nelems = sizeof ary / sizeof ary[0];

    printf("%d\n", nelems);  // 4

    return 0;
}

配列全体のバイト数を要素1つ分のバイト数で割ると要素数が求まります。
たとえば4バイトのint型の配列で要素数が4だった場合はどうなるでしょうか。
この場合は4 * 4 = 16バイトが配列全体のバイト数です。
要素1つは4バイトなので16 / 4 = 4になって要素数4が求まります。

sizeof演算子の注意点としてはポインタ変数から配列のサイズを求められないという点があります。

#include <stdio.h>

int main(void) {
    int ary[3];
    int *p = ary;

    printf("%ld\n", sizeof p);  // 8

    return 0;
}

ポインタ変数のサイズは環境によって違いますが64ビット環境だと8バイトになります。
先ほどの割り算で要素数を求める場合は左側の変数がポインタ変数でないか気を付ける必要があります。
これはC言語ではよくあるバグなので覚えておくと良いと思います。

numofマクロ

さきほどの割り算の式をマクロにしておくと便利に使えます。
たとえばnumofというマクロを作る場合は↓のようにします。

#define numof(ary) (sizeof ary / sizeof ary[0])

このマクロを使うとfor文のループは↓のように書けます。

#include <stdio.h>

#define numof(ary) (sizeof ary / sizeof ary[0])

int main(void) {
    int ary[] = {1, 2, 3};

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

    return 0;
}

配列をmemset()で初期化

配列の各要素はメモリ領域が連続しています。
そのためmemset()などの関数で初期化することもできます。

#include <stdio.h>
#include <string.h>

int main(void) {
    int ary[3];

    memset(ary, 0, sizeof ary);

    printf("%d\n", ary[0]);  // 0
    printf("%d\n", ary[1]);  // 0
    printf("%d\n", ary[2]);  // 0

    return 0;
}

memset(配列, セットする値, バイト数)で配列を初期化できます。
バイト数は配列全体のバイト数になります。
このバイト数が実際のサイズより大きいとセグフォなどのエラーになる場合があります。

配列を0クリアなどしたい場合にmemset()はよく使われます。

おわりに

今回はC言語の配列の書き方について解説しました。
C言語の配列は機能はそれほどありませんが慣れると便利に使うことができます。
覚えておきたいデータ構造と言えます。

(^ _ ^)

配列でデータを管理

(・ v ・)

総番号化の管理体制



この記事のアンケートを送信する