第十一回-03 関数に配列へのポインタを渡す



関数に配列へのポインタを渡す (1)

さて、本日の総仕上げとして「関数に配列へのポインタを渡す」例を見ていこう。
今、前提として ということを考えよう。 そのようなプログラムは C 言語の範囲では常套手段である。

第十回-02 アドレスとポインタ (1)で学んだように、別の関数へデータ (引数) を渡す際は値をコピーすることで関数に渡される。
しかし、例えば「要素数100の配列を渡すために、100 個のデータをコピーするのか」というと、そういうわけには行かない。
というのも、1 個や2 個ならともかく、100 個のデータをメモリ上でいちいちコピーするのは非常に無駄であるからである。

実際、今回扱って来た例で「配列に偶数を格納する (値をセットする)」という機能を別関数に分けてみた例は以下の通りである。

まずは、配列の要素数をコンパイル前に定数 5 として与える場合。
関数 data_set への引数が、ポインタになっていることに注目。ここに配列の先頭アドレスを渡すのである。

#include <iostream>

void data_set(int *data, int n);  // 配列に値をセットする関数のプロトタイプ
                                      // 配列の先頭のアドレス data と配列サイズ n を受け取る
int main(int argc, char* argv[])
{
	const int n=5;  // 配列の要素数を定数で定める
	int array[n];   // int 型の配列 

	data_set(array, n); // 配列へデータを与える仕事を別関数に任せる
                               // 配列 array の先頭アドレスは array とも書けることを利用。さらに要素数 n も渡す

	for(int i=0 ; i<n ; i++){
		std::cout << array[i] << "\n";  // 利用法はこれまで通り
	}

	return 0;
}

void data_set(int *data, int n){
	for(int i=0 ; i<n ; i++){
		data[i] = 2*i;   // ポインタ data に対して data[i] と書くことで配列へアクセスできる
	}
}


上記のプログラムにて、関数 data_set が実行されるときのメモリのイメージ図はこちら。
ポインタ data が、main 関数内の配列 array の先頭を指している所がポイントである。





関数に配列へのポインタを渡す (2)

次に、プログラム実行中にヒープ領域から配列を確保する場合はこちら。
配列名や配列の確保の仕方が違うだけで、関数呼び出し部と関数本体は先程と全く変わらないことに注意。

#include <iostream>

void data_set(int *data, int n);  // 配列に値をセットする関数のプロトタイプ
                                      // 配列の先頭のアドレス data と配列サイズ n を受け取る
int main(int argc, char* argv[])
{

	int n;         // 配列の要素数
	int *a_heap;   // int 型のポインタ(後に配列として用いる)

	std::cout << "配列の要素数を入力してください : ";
	std::cin >> n;       // 配列の要素数をキーボードから打ち込む

	a_heap = new int[n]; // new 演算子で整数 n 個分のメモリを確保
                             // 要素数 n 個の配列として用いることができる

	data_set(a_heap, n); // 配列へデータを与える仕事を別関数に任せる
                                // 配列の先頭へのポインタ a_heap と要素数 n を渡す

	for(int i=0 ; i<n ; i++){
		std::cout << a_heap[i] << "\n";  // 利用法はこれまで通り
	}

	delete[] a_heap; // new 演算子で確保した領域は自分で delete で削除する!

	return 0;
}

void data_set(int *data, int n){
	for(int i=0 ; i<n ; i++){
		data[i] = 2*i;   // ポインタ data に対して data[i] と書くことで配列へアクセスできる
	}
}


ただし、data_set 実行中のメモリのイメージ図は若干異なる。
下図の様に、配列の実体はヒープ領域にあり、main 関数と data_set 関数の両方に、この配列の先頭を指すポインタが存在することになる。







←第十一回-02 new 演算子によるメモリの動的確保第十一回課題→

非情報系学生のための C/C++ 入門に戻る