next up previous contents
Next: メモリの解放 Up: C言語プログラミング上級編3 - メモリ管理 - Previous: C言語プログラミング上級編3 - メモリ管理 -   Contents

メモリの確保

確保されたメモリへのアクセスは、その番地を示すポインタを用いる。 ポインタ変数は、宣言時にはどの番地も指し示してはいないが 、 確保されたメモリの先頭アドレスをポインタへ代入することにより、 ポインタを介してメモリへのアクセスが可能となる。

動的にメモリを確保する関数には、malloc(), calloc(), realloc()関数がある。 これらの関数を使用する場合には、 stdlib.hを インクルードしなかけければならないmalloc()関数はメモリを確保する汎用関数である。 calloc()関数は配列を確保する関数である。また、 realloc()関数は、malloc(), calloc()関数で確保されたメモリのサイズを 変更する関数である。 以下、それぞれの仕様と機能概略を示す。


void *malloc(size_t size)
機能 : sizeで指定したバイト数のメモリを確保し、その番地を返す。
ただし、確保されたメモリは0クリアはされていない。


void *calloc(size_t nmemb, size_t size)
機能 : sizeで指定されたバイト数を持つ1つのレコードをnmemb個持つ配列を確保し、
その先頭番地を返す。
ただし、mallocとは違い、確保されたメモリは0クリアされる。


void *realloc(void *ptr, size_t size)
機能 : ptrが指し示したメモリのサイズを、sizeで指定されたバイト数に変更する。
sizeが以前に確保されたバイト数より大きい場合には、以前確保されたメモリ領域の内容は、
変更されることなく、大きめのメモリが確保される。
ptrがNULLの場合には、malloc()関数と同じ働きをする

なお、sizeに0を指定した場合に、NULLが返えされるかどうかは、処理系の仕様に依存する。 また、メモリが確保されなかった場合にはNULLが返ってくるので、 メモリが確保できなかった場合にエラーを出力してプログラムを終了するには、 例えば次のようにすればよい。


void *iptr;
if( ( iptr = malloc(sizeof(int))) == NULL ){
fprintf(stderr, ”メモリが確保できませんでした \n”);
exit(-1);
}

返り値がvoid *であるので、実際に使用するには、使用目的に応じた 型へ変換(キャスト)する必要がある。以下、メモリの確保とキャスト方法の例を示す。


int *iptr, *fptr, *dptr;
iptr = (int *)malloc(sizeof(int)* 10);
fptr = (float *)calloc(10, sizeof(float));
dptr = (double *)malloc(sizeof(double)*100);
dptr = (double *)realloc(dptr, sizeof(double)*200);

上記の最後の1行では、その前の1行で確保したdouble型100個分のメモリを 200個分へ再確保している。 構造体の場合も同様の方法でメモリを確保することができる。 sizeの計算には、sizeof演算子を使用するのがベターである。 何故なら、同じint型であっても16ビットの処理系と32ビットの処理系では、 int型のサイズが異なるからである。また、構造体の場合、 メモリサイズの狭間が存在する場合があるので、 自分で構造体のサイズを計算するよりもsizeof演算子を使った方が 間違いが無いからである。



kojima hirohisa
2001-03-05