動的にメモリを確保する関数には、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
演算子を使った方が
間違いが無いからである。