プログラミングをしていると、「ユーザーが入力した文字数に合わせて、ちょうど良いサイズの入れ物(メモリ)を用意したい」といった場面に遭遇することがあります。C言語では、そんな時に役立つ「動的メモリ確保」という仕組みが用意されています。
この記事では、C言語のメモリ管理の基本である動的メモリ確保と、その中心的な役割を担うmalloc
関数およびfree
関数の使い方について、初心者の方にも分かりやすく解説します。
動的メモリ確保とは?
プログラムが使用するメモリを確保する方法には、大きく分けて「静的メモリ確保」と「動的メモリ確保」の2種類があります。
- 静的メモリ確保:
int data[20];
のように、プログラムを書く時点であらかじめ確保するメモリサイズが決まっている方法です。サイズが固定で、プログラムの実行中に変更することはできません。 - 動的メモリ確保: プログラムを実行している最中に、必要に応じて好きなサイズのメモリを確保する方法です。これにより、プログラムの柔軟性が格段に向上します。
例えば、ユーザーが入力する文章の長さに応じてメモリを確保する場合など、実行時まで必要なメモリ量が分からない状況で非常に役立ちます。
メモリを確保するmalloc
関数
動的メモリ確保を行うための最も基本的な関数が malloc
関数です。malloc
は “memory allocation” の略です。
malloc
関数は、標準ライブラリ(stdlib.h
)に含まれているため、使用する際はファイルの先頭でインクルードする必要があります。
malloc
関数の基本構文
#include <stdlib.h>
void* malloc(size_t バイト数);
- 引数: 確保したいメモリのサイズをバイト単位で指定します。
- 戻り値: 確保に成功した場合、確保されたメモリ領域の先頭アドレスを指すポインタ (
void*
型) を返します。もしメモリの確保に失敗した場合は、NULL
という特別な値を返します。
sizeof
演算子と組み合わせることで、「指定した型の変数が〇個入る領域」といった形で、より直感的にサイズを指定できます。
malloc
とfree
の実践的な使い方
それでは、実際にmalloc
関数を使って、ユーザーが指定した長さの文字列を格納するためのメモリを確保するプログラムを見ていきましょう。
メモリを確保した後は、使い終わったら必ず解放しなければなりません。そのために free
関数を使います。malloc
と free
は必ずセットで使うと覚えてください。
サンプルコード
#include <stdio.h>
#include <stdlib.h> // malloc, free を使うために必要
int main(void) {
int string_length = 0;
char *char_buffer = NULL; // ポインタはNULLで初期化するのが安全です
// ユーザーから必要な文字列の長さを入力してもらう
printf("確保したい文字列の長さを入力してください: ");
scanf("%d", &string_length);
// (入力された長さ + ヌル文字'\0'の1バイト分)のメモリを確保する
// sizeof(char)は常に1ですが、型のサイズを意識するために記述を推奨します
char_buffer = (char *)malloc(sizeof(char) * (string_length + 1));
// メモリ確保が成功したかチェックする (非常に重要!)
if (char_buffer == NULL) {
printf("メモリの確保に失敗しました。\n");
return 1; // 異常終了
}
printf("%d文字分のメモリを確保しました。アドレス: %p\n", string_length, char_buffer);
// ここで確保したメモリを使った処理を行う
// (例: 文字列を読み込んだり、書き込んだりする)
// 使い終わったメモリを必ず解放する
free(char_buffer);
printf("メモリを解放しました。\n");
// 解放後のポインタに再度アクセスしないようにNULLを代入しておくと、より安全です
char_buffer = NULL;
return 0; // 正常終了
}
コードの解説
- ヘッダのインクルード:
malloc
とfree
を使うために<stdlib.h>
をインクルードします。 - ポインタの初期化: ポインタ変数
char_buffer
をNULL
で初期化しています。これにより、万が一malloc
を呼び出す前に使おうとしても、プログラムがクラッシュしやすくなり、バグの発見に繋がります。 - メモリサイズの計算: ユーザーが入力した
string_length
に1
を足しています。これは、C言語の文字列が最後に必ず「ヌル文字 (\0
)」という終端マーカーを必要とするためです。この1バイトを忘れると、後々大きな問題を引き起こす可能性があります。 malloc
の呼び出しとキャスト:malloc
でメモリを確保します。malloc
の戻り値はvoid*
という汎用的なポインタ型なので、今回使いたいchar*
型に(char *)
という記述で**キャスト(型変換)**しています。- NULLチェック:
malloc
はメモリ確保に失敗するとNULL
を返します。もしNULL
が返ってきたのに、そのポインタを使おうとするとプログラムは即座にクラッシュします。そのため、malloc
の直後には、必ずif (char_buffer == NULL)
のようなチェック処理を入れるのが鉄則です。 free
によるメモリ解放:free(char_buffer);
で、malloc
を使って確保したメモリをシステムに返却します。これを忘れるとメモリリークという現象が発生し、プログラムが動き続けるうちに利用可能なメモリを食い潰してしまい、最終的にはシステム全体の動作が不安定になる原因となります。
まとめ
今回は、C言語における動的メモリ確保の基本である malloc
と free
について解説しました。
- 動的メモリ確保は、プログラム実行中に必要なサイズのメモリを確保する仕組み。
malloc
関数で、指定したバイト数のメモリを確保する。malloc
の後は、必ずNULLチェックを行う。- 使い終わったメモリは、必ず**
free
関数**で解放する。 malloc
とfree
は必ずペアで使用する。
動的メモリ確保は、ポインタの理解が必要なため少し難しく感じるかもしれませんが、C言語で柔軟なプログラムを作成するためには避けては通れない重要な機能です。この記事のサンプルコードを参考に、ぜひご自身で動かしながら学習を進めてみてください。