メモリの動的確保

配列の大きさは

int a[10];

のように宣言することにより、決まりました。これは、あらかじめ int 型の変数が 10 個必要である、とわかっていることが前提となります。しかし、実際プログラミングは、この個数がわからないことがよくあります。

ユーザーに整数型データを入力してもらい、その平均値を出すプログラムを考えてみましょう。入力したデータを int 型の配列にため込むとして、いくつの要素を用意すればよいでしょうか。ユーザーは何個のデータを入力するはわからないですね。

余裕をもって

int a[1000];

と宣言しますか?ユーザーがデータを3つしか入力しなかったら、メモリの無駄遣いです。もしかしてユーザーが1,000個より多いデータを入力したらどうなるでしょうか。

C言語では、必要なときに変数や配列などのメモリを確保する機能があります。。これをメモリの確保と呼びます。これを現実するには malloc 関数や calloc 関数を使います。

void *malloc(
             size_t size                                                                  
);

malloc 関数を使うには、malloc.h をインクルードします。「void *」型とは、どんな型にでもキャストできるという意味です。size には、割当てるバイト数を指定します。数値で xx バイトというように割当てても良いのですが、通常は sizeof 演算子を利用するので、size の型は size_t 型となっています。例えば int 型1個分の領域を確保するには、次のようにします。

int *pi;

pi = (int *)malloc(sizeof(int));

また、この関数が失敗したら NULL が返されます。プログラマは、malloc 関数の戻り値が NULL でないことを確認する必要があります。

さて、このように動的に確保したメモリは、不要になったらプログラマの責任で解放しなくてはいけません。これには free 関数を使います。

void free(
          void *memblock                                                                  
);

free 関数を使うには、stdlib.h をインクルードする必要があります。memblock には、解放するメモリブロックを指定します。

動的に確保したメモリは、不要になったら free 関数でする。

ソースコード

源文件
  1|/* malloc01.c */
  2|
  3|#include <stdio.h>
  4|#include <stdlib.h>                                                                   
  5|
  6|
  7|int main(void)
  8|{
  9|  int *pi;
 10|  /* int型1個分のメモリブロック確保 */
 11|  pi = (int *)malloc(sizeof(int));
 12|
 13|  if(pi == NULL){
 14|    perror("メモリの確保に失敗しました\n");
 15|    return -1;
 16|  }
 17|  *pi = 100;
 18|  printf("*pi = %d\n", *pi);
 19|
 20|  /* 不要になったらメモリは解放する */
 21|  free(pi);
 22|
 23|  return 0;
 24|}

実行結果

*pi = 100


peror 関数

エラーメッセージを出力します。
void perror(
            const char *string                                                            
);

perror 関数は、標準エラー(stderr)に文字列を出力します。この関数を使うには、 をインクルードする必要があります。標準エラーとは通常は画面のことです。printf は、標準出力に文字列を出力しました。通常、標準出力は画面です(ここではコマンドプロンプトウィンドウ)。しかし、リダイレクトすれば、標準出力が画面とは限りません。そこで、重要なエラーなど、どうしても画面に出力したい場合は perror 関数を使います。

perror("abc");

が実行されると abc の後ろにコロン(:)、スペース、エラーメッセージ(処理系によりいろいろ)、そして改行が出力されます。

ソースコード

源文件
  1|/* malloc02.c */
  2|
  3|#include <stdio.h>
  4|#include <stdlib.h>
  5|
  6|int main(void)
  7|{
  8|  int *pi, no, i;
  9|  printf("何個の整数値を入力しますか--");
 10|  scanf("%d", &no);
 11|  pi = (int *)malloc(sizeof(int) * no);
 12|  if(pi == NULL){
 13|    perror("メモリ確保に失敗しました\n");
 14|    return -1;
 15|  }
 16|  for(i = 0; i < no; i++){
 17|    printf("%d個目のデータ--", i + 1);
 18|    scanf("%d", pi + i);                                                              
 19|  }
 20|  printf("入力されたデータは次の通りです\n");
 21|  for(i = 0; i < no; i++){
 22|    printf("NO.%d = %d\n", i + 1, *(pi + i));
 23|  }
 24|  free(pi);
 25|  return 0;                                                                           
 26|}

実行結果

何個の整数値を入力しますか--4
1個目のデータ--100
2個目のデータ--23455
3個目のデータ--3244444
4個目のデータ--8765
入力されたデータは次の通りです
NO.1 = 100
NO.2 = 23455
NO.3 = 3244444
NO.4 = 8765


calloc 関数

メモリ配列を確保し、0で初期化します。
void *calloc(
             size_t num,
             size_t size                                                                  
);
num 個の要素を持つ配列を確保します。各要素のサイズは size バイトです。また、各要素は0で初期化されます。不要になったら free 関数で解放するのは malloc 関数と同じです。

ソースコード

源文件
/* calloc01.c */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
  char *pc;

  pc = (char *)calloc(16, sizeof(char));
  if(pc == NULL){
    perror("メモリの確保に失敗しました\n");
    return -1;
  }

  strcpy(pc, "あいうえお");
  printf("%s\n", pc);                                                                     
  free(pc);
  return 0;
}

実行結果

あいうえお

Chapter10 @ C言語目録 @ HomeWork List @ 昭亮's Homepage