工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> C言語

C 言語動的メモリ割り当て: malloc、calloc、realloc、free をマスター

C 言語の動的メモリ割り当てに入る前に、言語におけるメモリ管理の仕組みを理解することが不可欠です。

C 言語におけるメモリ管理の仕組み

プリミティブ型で変数を宣言すると、コンパイラは自動的に スタック 上に領域を確保します。例えば float は通常 4 バイト (プラットフォーム依存) を占有します。sizeof 演算子で確認できます:

#include <stdio.h>
int main() {
    float x;
    printf("The size of float is %d bytes", sizeof(x));
    return 0;
}

出力:

The size of float is 4 bytes

指定サイズの配列もスタック上に連続して割り当てられ、各要素はその型のサイズを占有します:

#include <stdio.h>
int main() {
    float arr[10];
    printf("The size of the float array with 10 elements is %d", sizeof(arr));
    return 0;
}

結果:

The size of the float array with 10 elements is 40

スタック割り当ては自動的ですが、多くのプログラムでは実行時までサイズがわからないメモリを必要とします。このニーズに応えるのが 動的メモリ割り当て で、スタックではなく ヒープ を使用します。

C 言語の動的メモリ割り当て

動的割り当てでは、必要に応じて手動でメモリを要求・解放し、ポインタでヒープ上の割り当てブロックを追跡します。C 標準ライブラリはいくつかの関数を提供します:

各関数を詳細に見ていきます。

malloc() 関数

malloc() は "memory allocation" の略。指定サイズのメモリブロックを確保し、そのポインタを返します。ポインタは通常目的の型にキャストして使用:

ptr = (cast_type *) malloc(byte_size);

例:

#include <stdlib.h>
int main() {
    int *ptr;
    ptr = malloc(15 * sizeof(*ptr)); /* 15 個の整数 */
    if (ptr != NULL) {
        *(ptr + 5) = 480; /* 6 番目の要素 */
        printf("Value of the 6th integer is %d", *(ptr + 5));
    }
}

出力:

Value of the 6th integer is 480

重要なポイント:

  1. sizeof(*ptr) を使用すると型変更に対して堅牢。
  2. 戻り値が NULL かチェックして割り当て失敗を検知。
  3. 割り当てメモリは連続。配列として扱いポインタ演算でアクセス可能。

動的割り当てはプリミティブ型に限らず、構造体、文字配列などにも適用可能。

free() 関数

malloc()、calloc()、realloc() で割り当てたメモリは、リークを防ぐため明示的に解放する必要があります。free() がこの役割を果たします:

#include <stdio.h>
int main() {
    int* ptr = malloc(10 * sizeof(*ptr));
    if (ptr != NULL) {
        *(ptr + 2) = 50;
        printf("Value of the 2nd integer is %d", *(ptr + 2));
    }
    free(ptr);
}

出力:

Value of the 2nd integer is 50

calloc() 関数

calloc() は同サイズの複数ブロックを割り当て、全バイトをゼロ初期化するため、ゼロ初期化が必要な配列や構造体に最適です:

ptr = (cast_type *) calloc(n, size);

例 – 等差数列の合計:

#include <stdio.h>
int main() {
    int i, *ptr, sum = 0;
    ptr = calloc(10, sizeof(int));
    if (ptr == NULL) {
        printf("Error! memory not allocated.");
        exit(0);
    }
    for (i = 0; i < 10; ++i) {
        *(ptr + i) = i;
        sum += *(ptr + i);
    }
    printf("Sum = %d", sum);
    free(ptr);
    return 0;
}

結果:

Sum = 45

calloc() vs malloc()

主な違い:

realloc() 関数

realloc() は既存割り当てのサイズを変更し、内容を保持します:

ptr = realloc(ptr, newsize);

例 – 文字列バッファの拡張:

#include <stdio.h>
int main() {
    char *ptr = malloc(10);
    strcpy(ptr, "Programming");
    ptr = realloc(ptr, 20); // 拡大
    strcat(ptr, " In 'C'");
    printf("%s, Address = %u", ptr, ptr);
    free(ptr);
    return 0;
}

再割り当て失敗時、realloc() は NULL を返し、元のブロックは有効なままです。

動的配列

動的配列は実行中に要素数を増やせるため、アルゴリズムやデータ構造で一般的なパターンです:

#include <stdio.h>
int main() {
    int *arr_dynamic = NULL;
    int elements = 2, i;
    arr_dynamic = calloc(elements, sizeof(int));
    for (i = 0; i < elements; i++) arr_dynamic[i] = i;
    for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]);
    elements = 4;
    arr_dynamic = realloc(arr_dynamic, elements * sizeof(int));
    printf("After realloc\n");
    for (i = 2; i < elements; i++) arr_dynamic[i] = i;
    for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]);
    free(arr_dynamic);
}

結果:

arr_dynamic[0]=0
arr_dynamic[1]=1
After realloc
arr_dynamic[0]=0
arr_dynamic[1]=1
arr_dynamic[2]=2
arr_dynamic[3]=3

まとめ

C言語

  1. ROM、PROM、EPROM、EEPROMの理解:設計、プログラミング、識別
  2. C# 入出力の基礎:ユーザー入力と出力の基本をマスター
  3. C# usingステートメント完全ガイド:名前空間インポート、エイリアス、静的ディレクティブ
  4. C++メモリ管理の極意:newとdeleteのエキスパート活用法
  5. C言語ユーザー定義関数の4つの実証済みパターン
  6. C言語 動的メモリ確保: malloc, calloc, realloc, free をマスターする
  7. C言語 標準ライブラリ関数: 実践ガイド
  8. C++動的配列の確保をマスター:コード例付き実践ガイド
  9. C++関数を実例で徹底解説:基本から応用まで
  10. C言語の関数マスター:構造、宣言、ベストプラクティス
  11. C言語動的メモリ管理:calloc、malloc、freeの解説