Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C言語の動的メモリ割り当てとは?malloc・calloc・realloc・freeの使い方を解説

この記事では、C言語における動的メモリ割り当て(Dynamic Memory Allocation)について詳しく解説します。C言語には、実行時に必要なメモリを確保・管理するための関数がいくつか用意されており、これらは <stdlib.h> ヘッダーファイルに定義されています。

C言語の主なメモリ管理関数

関数説明
void *calloc(int num, int size);num 個の要素を持つ配列用のメモリを割り当てます。各要素のサイズは size バイトで、メモリはゼロで初期化されます。
void free(void *address);address で指定されたメモリブロックを解放します。
void *malloc(int num);num バイトのメモリを割り当てます。割り当てられたメモリは初期化されません。
void *realloc(void *address, int newsize);割り当て済みメモリを newsize バイトまで拡張(または縮小)して再割り当てします。

メモリを動的に割り当てる

プログラミングの際、必要な配列のサイズが事前にわかっているのであれば、通常の配列として定義するだけで問題ありません。例えば、人名を保存する場合、最大でも100文字程度に収まるとわかっていれば、次のように定義できます。

char name[100];

しかし、保存するテキストの長さが事前にわからない場合、例えばトピックに関する詳細な説明文を保存したいようなケースではどうすればよいのでしょうか。このような場合、必要なメモリ量を指定せずに文字型ポインタだけを定義しておき、後から必要に応じてメモリを割り当てる方法が有効です。以下の例を見てみましょう。

サンプルコード

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

int main() {
    char name[100];
    char *description;

    strcpy(name, "Adam");

    /* メモリを動的に割り当てる */
    description = malloc(200 * sizeof(char));

    if (description == NULL) {
        fprintf(stderr, "Error - unable to allocate required memory\n");
    } else {
        strcpy(description, "Adam a DPS student in class 10th");
    }

    printf("Name = %s\n", name);
    printf("Description: %s\n", description);

    return 0;
}

実行結果

Name = Adam
Description: Adam a DPS student in class 10th

同じプログラムは calloc() を使っても書けます。malloc を以下のように calloc に置き換えるだけです。

description = calloc(200, sizeof(char));

このように動的メモリ割り当てを使えば、サイズを自由に指定でき、メモリを完全に制御できます。一度サイズを決めると変更できない通常の配列とは異なり、必要に応じて柔軟にメモリを管理できるのが大きなメリットです。

メモリサイズの変更と解放

プログラムが終了すると、OSが自動的にそのプログラムが割り当てたすべてのメモリを解放します。しかし、良いプログラミング習慣として、メモリが不要になった時点で free() 関数を呼び出して明示的に解放すべきです。特に長時間動作するプログラムでは、メモリリークを防ぐために重要です。

また、realloc() 関数を呼び出すことで、割り当て済みメモリブロックのサイズを拡大・縮小することもできます。先ほどのプログラムを realloc() と free() を使うように書き直してみましょう。

サンプルコード

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

int main() {
    char name[100];
    char *description;

    strcpy(name, "Adam");

    /* メモリを動的に割り当てる */
    description = malloc(30 * sizeof(char));

    if (description == NULL) {
        fprintf(stderr, "Error - unable to allocate required memory\n");
    } else {
        strcpy(description, "Adam a DPS student.");
    }

    /* より長い説明文を保存したい場合 */
    description = realloc(description, 100 * sizeof(char));

    if (description == NULL) {
        fprintf(stderr, "Error - unable to allocate required memory\n");
    } else {
        strcat(description, "He is in class 10th");
    }

    printf("Name = %s\n", name);
    printf("Description: %s\n", description);

    /* free() 関数でメモリを解放する */
    free(description);

    return 0;
}

実行結果

Name = Adam
Description: Adam a DPS student.He is in class 10th

もし上記の例で realloc() によるメモリの再割り当てを行わなかった場合、description に利用可能なメモリが不足するため、strcat() 関数はバッファオーバーフローなどの未定義動作を引き起こします。このように、必要なメモリ量が変化する場面では realloc() が非常に役立ちます。

まとめ

C言語の動的メモリ割り当てを使いこなすことで、実行時に必要なメモリ量を柔軟に管理できます。malloc() でメモリを確保し、calloc() でゼロ初期化されたメモリを確保し、realloc() でサイズを変更し、free() で解放する。これら4つの関数を適切に組み合わせることが、効率的で安全なCプログラミングの鍵となります。

  1. 動的IPアドレスとは?仕組み・メリット・デメリットをわかりやすく解説

    動的IPアドレスとは動的IPアドレス(ダイナミックIPアドレス)とは、スマートフォン、デスクトップPC、ワイヤレスタブレットなど、ネットワークに接続する各機器(ノード)に対して自動的に割り当てられるIPアドレスのことです。この自動割り当ては、「DHCPサーバー」と呼ばれる仕組みによって実現されています。DHCPサーバーが割り当てたIPアドレスが「動的(ダイナミック)」と呼ばれる理由は、次回以降ネットワークに接続する際に、前回とは異なるIPアドレスが割り当てられることが多いからです。動的IPアドレスの対義語にあたるのが「静的IPアドレス(スタティックIPアドレス)」です。こちらは手動で設定された

  2. C言語における静的メモリ割り当てとは?仕組みとサンプルコードで徹底解説

    C言語でプログラムが使用するメモリは、大きく分けて「静的メモリ割り当て」と「動的メモリ割り当て」の2つの方法で確保されます。 静的メモリ割り当て(Static Memory Allocation)とは 静的メモリ割り当てとは、変数のサイズがプログラムの実行前に決定され、固定サイズの領域として割り当てられる方式です。一度確保されたメモリは、明示的に解放することはできません。プログラム内で宣言された変数に対して、あらかじめメモリが割り当てられます。 静的メモリ割り当ての主な特徴 アドレス演算子「&」を使って変数のアドレスを取得し、ポインタに代入することができます。 メモリはコンパイル時