malloc() と free()

C言語では、配列の大きさはコンパイル時に(というかプログラムを書いた時点で) 決まるものでなければなりません。 たとえば、int n; int a[n]; という宣言は不可能です。

プログラムが動いてから配列の大きさを決めたい場合は、 関数 malloc() で割り当ててやります。 この機能が実際に役立つようなプログラムはやや大規模になってしまうので、 やや“苦しい”例を示します。

#include <stdio.h>
#include <stdlib.h> /* malloc() */

main() {
     int n;
     int *a;

     printf("何個の配列をとりますか?\n");
     scanf("%d", &n);
     a = (int *) malloc(sizeof(int) * n);
     if (a == NULL) {
         printf("メモリが足りません.\n");
         return 1;
     }
     /* ここで肝心の計算を行なう。省略 */
     free(a);
}
以下では「ポインタ」「アドレス」という概念を使って説明しますが、 知らない人にもそれなりにわかるように書いたつもりです。

まず、「int *a;」は a が int へのポインタである、という宣言です。 その上で宣言されている int n; とは別物なので、別の文にすることを私は勧めます。 b も int へのポインタなら「int *a, *b;」とも書けますが、 別の文にして「int *a; int *b;」としても OK です。

malloc() は、 引数で指定された大きさのメモリをどこかから取ってきて、 その先頭アドレスを返す関数です。 sizeof(int) は一つの int 型変数ががメモリに占めるバイト数。 (int *) は、malloc() の返す void へのポインタを int へのポインタに変換せよ、 ということです。 double の配列を取りたいなら、int をすべて double に変えてください。 malloc() によるメモリの割り当ては、メモリが不足して失敗することもあります。 その場合は NULL ポインタが返ることになっているので、 a に代入された値を使う前に if 文でチェックを行なわなければなりません。 このあたり全体で決まり文句と思ってもいいでしょう。

もしもメモリの割り当てに成功していたら、 a は配列名と同じように使えます。 つまり、もしも上のプログラムを動かして、 n に 100 を代入して malloc() に成功したら、 そのあとでは int a[100]; と書いてあったかのように a[0], a[1], ..., a[99] が使えます。

用が済んだら、free() で a を解放します。 解放できるのは、malloc()(およびここでは紹介しなかった類似の関数) で割り当てられたメモリだけです。 もし解放しなくても、プログラムが終わってしまえば解放されるので、 この例では実は不要なのでした。


岩瀬順一