配列の全要素を同じ値で埋める | Programming Place Plus C言語編 逆引き

トップページC言語編逆引き

このページの概要

以下は目次です。

目的

定義済みの配列のすべての要素に、同じ値を入れたいとします。

#include <stdio.h>

#define SIZE_OF_ARRAY(array)    (sizeof(array)/sizeof(array[0]))

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

    // array[0]~array[4] まで、すべてを 10 にしたい
}

SIZE_OF_ARRAYマクロは、配列の要素数を取得するものです。詳細は「逆引き 配列の要素数を求める」を参照してください。

方法①(for文で1つずつ代入する)

for文を使って、要素1つ1つに順番に値を代入していきます。実のところ、この方法よりも確実な方法はありませんし、これより楽ができる方法もありません。

#include <stdio.h>

#define SIZE_OF_ARRAY(array)    (sizeof(array)/sizeof(array[0]))

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

    for (size_t i = 0; i < SIZE_OF_ARRAY(array); ++i) {
        array[i] = 10;
    }

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

実行結果:

10 10 10 10 10 

方法②(memset関数を使う ※ほぼうまくいかない)

memset関数を使うと、メモリの範囲を同じ値で埋めることができるため、これを使って、すべての要素を 0 で埋める方法が紹介されることがあります(「逆引き 配列の全要素を 0 で埋める」で取り上げています)。

指定する値を 0 以外にすれば、すべての要素を埋める手段として使えそうに思えますが、ほとんどの場合でうまくいきません。memset関数は「1バイト単位」で同じ値を埋める関数だからです。

【上級】memset関数はそもそも「文字」を書き込む関数なのであり、第2引数に指定した値を、unsigned char型に変換して書き込むという仕様です。

たとえば、int型の配列のすべての要素を 10 で埋めたいとします。

まず、int型の配列の各要素の大きさは sizeof(int) です。これは 4バイトであったり、2バイトであったりするでしょう。仮に 4バイトだとすると、その 4バイトを構成する 4つのバイトのそれぞれに、10 を入れるのが memset関数の仕様なのです。

次のサンプルプログラムは memset関数による方法を試したものですが、失敗しています。

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

#define SIZE_OF_ARRAY(array)    (sizeof(array)/sizeof(array[0]))

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

    // array の各要素に 10 を入れる?
    memset(array, 10, sizeof(array));

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

実行結果:

168430090 168430090 168430090 168430090 168430090

array[i] の 4バイトを構成する 4つのバイトそれぞれに 10 が書き込まれるため、このような結果になります。この実行結果ではわかりづらいかもしれませんが、“%x” 変換指定子を使って 16進数で出力すると状況が見えやすいでしょう。

実行結果(16進数で出力した場合):

a0a0a0a a0a0a0a a0a0a0a a0a0a0a a0a0a0a

10進数の「10」は、16進数で「a」ですから、それぞれ4つの「0a」が書き込まれている様子がみえます。

このように、memset関数を使って、すべての要素に同じ値を入れる方法は、うまくいかないケースがほとんどです。0 で埋める場合や、255(0xff)で埋める場合など、1バイト単位で書き込んでも、結果が変わらないケースでなければうまくいきません。

また、ポインタ型や、浮動小数点型の配列の場合、「0」が必ずしもヌルポインタや 0.0 のことを意味しないことに注意してください(「逆引き 配列の全要素を 0 で埋める」を参照)。


参考リンク


更新履歴

’2019/9/2 新規作成。



逆引きのトップページへ

C言語編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る