「要素数 4 の配列を渡してください」ではなく「要素数 4 の配列を渡さなければならない」にする

  • 39
    Like
  • 0
    Comment
More than 1 year has passed since last update.

例えば、何も考えずに配列を引数で受け取る関数を考えるとします。
すると、以下のようになるかと思います。

test.cpp
#include <iostream>

void Func(const short array[4])
{
    using namespace std;

    for (int i = 0; i < 4; ++i) {
        cout << array[i] << endl;
    }
}

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

    Func(array);
    return 0;
}

ぱっと見、なんの問題もないように見えますが、実はこれ、 配列ではなく単なるポインタ扱い になっています。

どういうこっちゃ?どう見ても配列でしょ?と思うかもしれませんが、
以下のコードと実行結果を見れば一目瞭然です。

test2.cpp
#include <iostream>

void Func(const short array[4])
{
    using namespace std;
    cout << sizeof(array) << endl;
}

int main()
{
    using namespace std;

    short array[4] = {};
    cout << sizeof(array) << endl;

    Func(array);
    return 0;
}
output
8
4

関数外で sizeof すると、配列のサイズである 8 が出力されています。
が、関数内で sizeof するとあら不思議。出力されているのは 4 です。

この 4 はなんの 4 なのか?と言うと、これこそが short * のサイズである 4 となるわけです。

よって

void Func(const short array[4])

void Func(const short * array)

と同義というわけです。

まぁ、これでも 「short 型の要素数 4 の配列を渡してください」 という意図を伝えることはできますが、
残念ながら 「short 型の要素数 4 の配列を渡さなければならない」 ことにはできません。

あくまで short * なので、short * であれば、要素数が 10 でも 100 でも、
更には new したポインタ でさえ渡すことができちゃうわけです。


これをなんとか「short 型の要素数 4 の配列を渡さなければならない」ことにできないか?


これを実現できるのが 「配列の参照」 です。
百聞は一見にしかず。というわけで、コードと実行結果です。

test3.cpp
#include <iostream>

void Func(short (&array)[4])
{
    using namespace std;
    cout << sizeof(array) << endl;
}
int main()
{
    using namespace std;

    short array[4] = {};
    cout << sizeof(array) << endl;

    Func(array);
    return 0;
}
output
8
8

(&array)[4] が「配列の参照」となります。
() 重要です。ないとコンパイルエラーで怒られます。

実行結果を見ると、関数内、関数外の両方で 8 が出力されてますね。
8 が出力されているということは、「short 型の要素数 4 の配列」として認識されているということです。

という訳で、これで無事に「short 型の要素数 4 の配列を渡さなければならない」を実現することが出来ました。

ちなみに、きちんと配列として認識されていますので、

for (int i = 0; i < SIZEOF_ARRAY(array); ++i) {
    cout << array[i] << endl;
}

こんなこともできます。