C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++の配列減衰(Array Decay)とは?原因と防止方法を解説

配列減衰(Array Decay)とは

配列の型やサイズ(次元)の情報が失われる現象は、「配列減衰(array decay)」と呼ばれます。この現象は、配列を関数へポインタや値として渡したときに発生します。その際に関数へ渡されるのは配列の先頭アドレス、つまりポインタであるため、関数側では元の配列サイズを知ることができません。

ここでは、C++における配列減衰の具体例を見てみましょう。

サンプルコード

#include<iostream>
using namespace std;

void DisplayValue(int *p) {
    cout << "値渡しした場合の配列のサイズ : ";
    cout << sizeof(p) << endl;
}

void DisplayPointer(int (*p)[10]) {
    cout << "ポインタ渡しした場合の配列のサイズ : ";
    cout << sizeof(p) << endl;
}

int main() {
    int arr[10] = {1, 2};
    cout << "配列の実際のサイズ : ";
    cout << sizeof(arr) << endl;
    DisplayValue(arr);
    DisplayPointer(&arr);
    return 0;
}

実行結果

配列の実際のサイズ : 40
値渡しした場合の配列のサイズ : 8
ポインタ渡しした場合の配列のサイズ : 8

このように、sizeof(arr) では int 型10個分の40バイトが返されますが、関数に渡した後の sizeof(p) はポインタ自体のサイズ(64ビット環境では8バイト)を返すため、元の配列サイズは失われてしまいます。

配列減衰を防ぐ方法

配列減衰を防ぐには、主に次の2つの方法があります。

  • 配列のサイズを別の引数として関数に渡し、配列を受け取るパラメータに対して sizeof() を使用しない。

  • 配列を参照渡しで関数に渡す。これにより配列からポインタへの暗黙的な変換が起こらず、配列減衰を防げます。

続いて、C++で配列減衰を防ぐ具体例を紹介します。

サンプルコード

#include<iostream>
using namespace std;

void Display(int (&p)[10]) {
    cout << "参照渡しした場合の配列のサイズ: ";
    cout << sizeof(p) << endl;
}

int main() {
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    cout << "配列の実際のサイズ: ";
    cout << sizeof(arr) << endl;
    Display(arr);
    return 0;
}

実行結果

配列の実際のサイズ: 40
参照渡しした場合の配列のサイズ: 40

参照渡しにすることで、関数内でも元の配列サイズ(40バイト)が正しく取得できていることがわかります。なお、現代のC++では std::arraystd::vector を利用すれば、サイズ情報を保持したまま安全に配列を扱えるため、用途に応じてこれらの活用も検討するとよいでしょう。

  1. C++で配列を最大・最小交互形式に並べ替えるプログラム

    整数型の配列が与えられます。この配列はソート済みの場合もあれば、未ソートの場合もあります。求められるタスクは、まず配列が未ソートであれば昇順にソートし、その後、配列を次のような順序で並べ替えることです。 つまり、1番目の要素には最大値、2番目の要素には最小値、3番目の要素には2番目に大きい値、4番目の要素には2番目に小さい値……というように、最大と最小を交互に配置していきます。 入出力シナリオの例 入力 − int arr[] = {7, 5, 2, 3, 4, 9, 10, 5} 出力 − 並べ替え前の配列: 2 3 4 5 5 7 9 10最大最小形式に再配置した配列: 10 2 9 3

  2. 画像配列(イメージアレイ)とは?OpenCVとC++のサンプルコードでわかりやすく解説

    配列(アレイ)とは、複数のデータをまとめて効率的に格納し、取り出すための便利な仕組みです。OpenCVでは、この配列の概念を活用することで、複数の画像をひとつの「画像配列」に読み込み、インデックス番号を指定するだけで目的の画像を表示できます。 本記事では、Mat型の行列配列に複数の画像を読み込み、インデックス番号を使って各画像を表示するC++のサンプルプログラムを紹介します。 画像配列の基本的な考え方 通常、1枚の画像を読み込む場合はMatオブジェクトを1つ宣言すれば十分ですが、複数の画像を扱いたい場合には、Mat型の配列を宣言することで管理が簡単になります。配列の各要素にはimread()関