calloc関数とmalloc関数は、メモリ領域を確保します。calloc関数で確保したメモリ領域は0(全ビットが0のバイト)で初期化されているのに対して、malloc関数で確保したメモリ領域は初期化されません。
realloc関数は、calloc関数または、malloc関数で確保したメモリ領域の大きさを変更します。領域を大きくした場合は、元の領域の内容は変更されません。
free関数は、上記関数で確保したメモリ領域を解放します。
#include <stdlib.h>
void *calloc(size_t nmemb, size_t size);
void *malloc(size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
nmembは確保する要素の大きさをバイト単位で指定します。
sizeは、calloc関数の場合は要素の数を、malloc関数とrealloc関数の場合は、確保するメモリ領域の大きさをバイト単位で指定します。
*ptrは、realloc関数の場合はサイズを変更する領域のポインタを、free関数の場合は解放する領域のポインタを指定します。
戻り値として、calloc関数、malloc関数、realloc関数の場合は、確保したメモリ領域のポインタが返ります。失敗した場合はNULLが返ります。free関数の戻り値はありません。
次の例題プログラムは、ファイルの内容を構造体配列に読み込みますが、構造体配列を動的に確保(malloc関数使用)しています。また、確保した領域が余った場合は、縮小(realloc関数使用)しています。
プログラム 例
#include <stdio.h> #include <stdlib.h> /* メンバーの最大人数 */ #define MEMBER_MAX 20 /* メンバーの個人情報 */ struct member { int number; /* 番号 */ char name[20]; /* 名前 */ double height; /* 身長 */ double weight; /* 体重 */ double jump; /* 最高到達点 */ }; /* qsort関数のソートキー比較関数 */ int SortComp(const void *, const void *); int main() { FILE *fp; struct member *member_ptr; /* member構造体の配列 */ struct member *list_ptr; /* member構造体の要素 */ int list_max; /* member構造体の使用要素数 */ int list_cnt; if ((fp = fopen('beijing_2008.csv', 'r')) == NULL) { fprintf(stderr, 'ファイルのオープンに失敗しました\n'); abort(); } /* メンバー情報を登録するmember構造体の配列を確保 */ if ((member_ptr = malloc(sizeof(struct member) * MEMBER_MAX)) == NULL) { fprintf(stderr, 'メモリの確保に失敗しました\n'); abort(); } list_max = 0; list_ptr = member_ptr; /* メンバー情報入力 */ while(fscanf(fp, '%d,%[^,],%lf,%lf,%lf', &list_ptr->number, list_ptr->name, &list_ptr->height, &list_ptr->weight, &list_ptr->jump) != EOF) { ++list_ptr; ++list_max; if (list_max >= MEMBER_MAX) { break; } } fclose(fp); /* member構造体の配列に未使用な領域があったら、縮小 */ if (list_max < MEMBER_MAX) { if ((member_ptr = realloc(member_ptr, sizeof(struct member) * list_max)) == NULL) { fprintf(stderr, 'メモリの縮小に失敗しました\n'); abort(); } } /* member_listを名前をキーにしてソート */ qsort(member_ptr, list_max, sizeof(struct member), SortComp); list_ptr = member_ptr; printf('番号 名前 身長 体重 最高到達点\n'); /* ソート後のメンバー情報出力 */ for (list_cnt = 0; list_cnt < list_max; ++list_cnt, ++list_ptr) { printf('%3d %-20s %6.1f %6.1f %6.1f\n', list_ptr->number, list_ptr->name, list_ptr->height, list_ptr->weight, list_ptr->jump); } /* member構造体の配列を開放 */ free(member_ptr); return 0; } /* qsort関数のソートキー比較関数 */ int SortComp(const void *p1, const void *p2) { struct member *cmp1 = (struct member *)p1; struct member *cmp2 = (struct member *)p2; return strcmp(cmp1->name, cmp2->name); }
例の実行結果
$ cat beijing_2008.csv 1,kurihara,186,69,305 2,tajimi,180,70,309 3,takesita,159,52,280 4,oomura,184,70,319 5,takahasi,170,65,290 6,sano,159,54,260 7,sugiyama,184,66,310 8,sakurai,167,63,290 9,kanou,174,65,298 11,araki,186,79,307 12,kimura,184,66,298 14,kawai,168,63,280 $ $ ./mem_alloc.exe 番号 名前 身長 体重 最高到達点 11 araki 186.0 79.0 307.0 9 kanou 174.0 65.0 298.0 14 kawai 168.0 63.0 280.0 12 kimura 184.0 66.0 298.0 1 kurihara 186.0 69.0 305.0 4 oomura 184.0 70.0 319.0 8 sakurai 167.0 63.0 290.0 6 sano 159.0 54.0 260.0 7 sugiyama 184.0 66.0 310.0 2 tajimi 180.0 70.0 309.0 5 takahasi 170.0 65.0 290.0 3 takesita 159.0 52.0 280.0 $