第23回

動的に・・・

98/11/06 IE4.xに対応させた

今さら書くまでもないですが、例えば20個のint型の値を格納できる配列aを作成する場合、int型の配列aを以下のように宣言しておく必要があります。
int a[20];
それでは、いくつかのint型の値を格納できる配列aを作成する場合、どうすればいいでしょうか?

ここで問題となるのは、int型の値が何個あるのか明らかにされていないということです。

そこで、仮に多めに確保することにして

int a[100];
と宣言したとします。これで取りあえず、100個のint型の値が格納できるようになりました。でも、実際には101個の値を格納しなければならないかもしれません。逆に格納する値がわずか2個だけだったとしたら、残る98個の配列に割り当てられたメモリが無駄になってしまいます。

要するに、101個の値を格納したい時は101個の配列を、2個の値を格納したい時は2個の配列を状況に応じて用意できればいいわけです。しかし今までのやり方では、そう上手くはいきません。なぜなら配列を宣言する為には、プログラムを作成する段階で、配列の数を決めておかなければならないからです。

そういった時に用いるのが、標準ライブラリのmalloc関数とfree関数(あ。取りあえずコイツら)です。超簡単に説明すると、mallocで必要なメモリの領域を動的に確保して、使い終わったらfreeでその領域を解放する、といった感じです。それでは実際に、この方法で101個のint型の配列に必要なメモリ領域を(mallocで)動的に確保して、そしてそれを(freeで)開放するプログラムを作成してみることにします。

#include<stdio.h>
#include<stdlib.h>
main(){
    int *a;
    a=malloc(sizeof(int)*101);
    /*  ここに実際の処理が入る  */
    free(a);
}    
まず注目すべき点は、ヘッダファイルstdlib.hがインクルードされていることです。この中で、malloc関数は以下のように宣言されています。
void    *malloc(size_t);
とりあえず、戻り値の型がvoid型へのポインタ(void *)であることと、仮引数が受け取るのは必要なメモリ(バイト)であることを覚えておいて下さい。
また、ついでにfree関数の方も確認しておきます。
void    free(void *);

今度は、mainの中を見てみましょう。
まず、int型変数のポインタaが宣言されています。
    int *a;
そしてその次の行で、malloc関数の戻り値(確保した領域の先頭アドレス)が、先程のint型変数のポインタaに代入されています。

    a=malloc(sizeof(int)*101);
malloc関数の戻り値がvoid型へのポインタであるのに対して、その値を代入するポインタaはint型変数のポインタです。一見、型が合わないように思えますが、ANSI規格のC言語では、malloc関数の戻り値の型は、void*から自動的に必要なポインタ型に変換されるのです
ANSI規格のC言語じゃないC言語を使っている方は、
    a=(int *)malloc(sizeof(int)*101);
といった具合に型キャスト(って、まだ学んでいないか・・・)すればいいと思います。型キャストについては後々学ぶことにしましょう。
それと、先程も記しましたが、malloc関数が仮引数で受け取るのは必要なメモリ(バイト)です。ここでは、101個分のint型の配列に必要なサイズをバイト数で渡しています。ここで注意してほしいのが、貴方のマシンのint型のサイズが2バイトだからといって(2バイト*101=202バイトだから)、

a=malloc(202);

とするのは止めてほしいということです。と、いうのは、型のサイズは機種によって違う場合があるからです。必ずしもchar型は1バイト、int型は2バイトではありません。で、そういう時は、前回登場したsizeof演算子を使います。この演算子はサイズをバイト数で返します。つまりint型の配列101個のサイズは、sizeof(int)*101といった方法で求めるようにして下さい。

そして割り当てたメモリを開放したい時(っていうか、使い終わったら必ず開放して下さい)は、

    free(a);
と書けばいいです。

それでは、参考までに超簡単なプログラムを載せておきましょう。
#include<stdio.h>
#include<stdlib.h>
main(){
    int *a;
    /* 型キャストしておいた:-) */
    a=(int *)malloc(sizeof(int)*3);
    a[1]=2;
    a[2]=3;
    a[0]=a[1]+a[2];

    printf("%d\n",a[0]);
    printf("%d\n",*(a+1)); /*  a[1]と同じ  */
    free(a);
}
実行結果は、
5
2
つづく。

[メニュー][第22回][第24回]

いーざ
email:CQP00202@nifty.ne.jp