第 7 章 ポインタ 31
7.4 ポインタを用いた動的なメモリアロケーション
プログラムを作成している時点で,あらかじめ使用する配列の大きさ(言い換えればメ モリの大きさ)がわかっている場合には,配列の宣言の時点で必要なサイズの配列を確保 すれば事足りる.しかしながら,実際にはプログラムを実行する時点まで,実際に用いる メモリサイズが不明な場合が少なくない.
例えば,1000名分のテストの点数の和を求めたり,平均点を求めたりするのであれば,
配列のサイズを1000として宣言すればよいが,実際にはプログラムを実行する時点で,
さらに多くの点数(1000を越える) を取り扱いたいようなケースも有り得る.すなわち,
配列を宣言することにより計算の上限数を決めてしまうのではなく,プログラムが実行さ れる時点で,必要量に応じたメモリ(配列)を確保するほうが都合がよい.
第7章 ポインタ 35 ここで述べているように,プログラムを実行した段階で任意に,必要なだけのメモリ領 域を確保することを,動的なメモリアロケーションと呼ぶ.以前の例題のように配列宣言 の時点でその大きさを指定する方法は,静的なメモリアロケーションと呼んで区別する.
動的なメモリアロケーションには, malloc という関数を用いる. 例えば, 先の例題 7–1 のように, 整数1000個分の領域を確保したい場合の書式は以下のとおりとなる.
p = (int*) malloc( 1000*sizeof(int) );
ここで, 1000 * sizeof(int) は文字通り整数1000個分のメモリ領域の大きさを表
しており,そのメモリ領域の先頭アドレスが,ポインタ型変数 p に格納される. 上の例で
は, malloc により得られるポインタが (int*) により型変換されているが, これは関数
malloc が返すポインタの型が標準で char*型(すなわち文字型変数へのポインタ)である
ためである. もちろん上記の構文は,メモリを確保する領域の大きさ, その要素の型(実数, 整数,文字型)によって適宜書き換えて用いることができる.
例題7–3 先の例題 7–1 を動的なメモリアロケーションを用いて書き換えよ. 解答例
1: #include <stdio.h>
2: #include <stdlib.h>
3: int main(void){
4: int *a;
5: int i, total;
6: a = (int*) malloc (1000 * sizeof(int));
7: if ( a == NULL ){
8: printf( "大きすぎてメモリが確保できません!\n");
9: exit(0);
10: }
11: for ( i = 0 ; i < 1000 ; i++ ){
12: a[i] = i + 1;
13: }
14: total = 0;
15: for ( i = 0 ; i < 1000 ; i++ ){
16: total = total + a[i];
17: }
18: printf( "1から1000までの合計は = %d\n", total);
19: return(0);
20:}
<注意>
1,2行目 関数mallocおよび NULLポインタを用いるためのinclude宣言.
4行目 変数 aは 整数へのポインタ型変数として宣言する.
7行目 mallocは領域が確保できなかった場合にヌルポインタ(NULL)を返す.
12, 16行目 このプログラムでは意図的に配列の書式で記述した.
もちろんポインタ型の記法*(a + i)のようにも書ける.
第7章 ポインタ 36
<演習問題7–1>
初項,公差,項数をscanf関数を用いて読み込み,その等差数列の和を求めるプログラ ムを完成させなさい.なお,和を求める際は公式を用いず,一項ずつ加えて計算すること とし,等差数列の各項を一旦メモリに格納してから和を求めるようにプログラムを作成 すること.また,メモリ領域(配列)は,動的なメモリアロケーションを用いて確保する こと.
1: #include <stdio.h>
2: #include <stdlib.h>
3: void main(){
4: int *p;
5: int a0, d, i, N;
6: printf("初項は?");
7: scanf("%d", &a0);
8: printf("公差は?");
9: scanf("%d", &d);
10: printf("項数は?");
11: scanf("%d", &N);
12: p = (int*) malloc ( N * sizeof(int) );
13: for ( i = 0 ; i < N ; i++ ){
14: ....
15: }
※あとは自分で考えてみてください.
scanf関数の引数はアドレスです.注意してください!
37