0Pricing
C Academy · レッスン

calloc と realloc

ゼロ初期化とメモリ拡張です。

「calloc と realloc」はCoddyKit上の無料C Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。

mallocのその先

malloc以外にも、標準ライブラリにはゼロ初期化されたメモリを確保するcallocと、既存のブロックのサイズを変更するreallocがあります。

どちらも<stdlib.h>に含まれています。

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

int main(void) {
    int *p = calloc(3, sizeof(int));
    printf("%d %d %d\n", p[0], p[1], p[2]);
    free(p);
    return 0;
}

callocはメモリをゼロにする

calloc(count, size)は、sizeバイトの要素をcount個格納できる領域を確保し、すべてのバイトをゼロに設定します。

初期状態がきれいなメモリが必要な場合に便利です。

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

int main(void) {
    int *a = calloc(5, sizeof(int));
    int sum = 0;
    for (int i = 0; i < 5; i++) sum += a[i];
    printf("sum of zeroed array = %d\n", sum);
    free(a);
    return 0;
}

callocには2つの引数がある

mallocとは異なり、callocは個数と要素サイズを別々に受け取ります。

また、個数とサイズを掛け合わせる際のオーバーフローも防止します。

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

int main(void) {
    double *d = calloc(4, sizeof(double));
    d[2] = 1.5;
    printf("%f %f\n", d[0], d[2]);
    free(d);
    return 0;
}

mallocとcallocの比較

すべてのバイトを上書きする場合はmallocを使用し、メモリがゼロで始まることを前提とする場合はcallocを使用します。

callocはゼロ初期化を行うため、少しコストが高くなります。

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

int main(void) {
    int *m = malloc(2 * sizeof(int));
    int *c = calloc(2, sizeof(int));
    m[0] = 5; m[1] = 6;
    printf("malloc: %d %d\n", m[0], m[1]);
    printf("calloc: %d %d\n", c[0], c[1]);
    free(m); free(c);
    return 0;
}

reallocで拡張する

realloc(ptr, newsize)はブロックのサイズを変更し、元のサイズと新しいサイズの小さい方まで既存の内容を保持します。

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

int main(void) {
    int *a = malloc(2 * sizeof(int));
    a[0] = 1; a[1] = 2;
    a = realloc(a, 4 * sizeof(int));
    a[2] = 3; a[3] = 4;
    for (int i = 0; i < 4; i++) printf("%d ", a[i]);
    printf("\n");
    free(a);
    return 0;
}

reallocはブロックを移動することがある

空き領域を探すためにブロックを移動する場合、reallocは異なるアドレスを返すことがあります。

結果は必ず代入し直し、古いポインターを使い続けないでください。

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

int main(void) {
    int *a = malloc(sizeof(int));
    a[0] = 42;
    int *bigger = realloc(a, 100 * sizeof(int));
    printf("first element still %d\n", bigger[0]);
    free(bigger);
    return 0;
}

安全なreallocのパターン

reallocが失敗するとNULLを返しますが、元のブロックはそのまま残ります。

失敗時に古いポインターを失わないよう、まず一時変数に代入してください。

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

int main(void) {
    int *a = malloc(2 * sizeof(int));
    int *tmp = realloc(a, 8 * sizeof(int));
    if (tmp == NULL) {
        free(a);
        return 1;
    }
    a = tmp;
    a[7] = 99;
    printf("%d\n", a[7]);
    free(a);
    return 0;
}

ブロックを縮小する

reallocではブロックを小さくすることもできます。先頭の要素は保持され、残りは解放されます。

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

int main(void) {
    int *a = malloc(6 * sizeof(int));
    for (int i = 0; i < 6; i++) a[i] = i;
    a = realloc(a, 3 * sizeof(int));
    printf("%d %d %d\n", a[0], a[1], a[2]);
    free(a);
    return 0;
}

拡張するバッファー

配列がいっぱいになると容量を2倍にするのが一般的なパターンです。これにより、拡張のコストを分散できます。

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

int main(void) {
    int cap = 2, len = 0;
    int *a = malloc(cap * sizeof(int));
    for (int v = 0; v < 5; v++) {
        if (len == cap) {
            cap *= 2;
            a = realloc(a, cap * sizeof(int));
        }
        a[len++] = v;
    }
    printf("len=%d cap=%d last=%d\n", len, cap, a[len-1]);
    free(a);
    return 0;
}

reallocにNULLを渡す

realloc(NULL, size)は、malloc(size)とまったく同じように動作します。

これにより、拡張処理で最初のメモリ確保も一律に扱えます。

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

int main(void) {
    int *a = realloc(NULL, 3 * sizeof(int));
    a[0] = 7;
    printf("%d\n", a[0]);
    free(a);
    return 0;
}

組み合わせて使う

最初にcallocでゼロ初期化されたバッファーを作成し、後からreallocで拡張できます。拡張後に追加されたバイトはゼロ初期化されません。

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

int main(void) {
    int *a = calloc(2, sizeof(int));
    a = realloc(a, 4 * sizeof(int));
    a[2] = 0; a[3] = 0;
    printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]);
    free(a);
    return 0;
}

理解度チェック

callocとreallocについての知識を確認しましょう。

まとめ

さらに2つのメモリ確保ツールを学びました。

  • calloc(count, size)はゼロ初期化されたメモリを確保し、乗算時のオーバーフローを防ぎます。
  • realloc(ptr, newsize)はブロックのサイズを変更し、移動することもあります。
  • 失敗時のリークを避けるため、reallocの結果は必ず一時変数に代入します。
  • realloc(NULL, size)はmallocと同じように動作します。

よくある質問

「calloc と realloc」レッスンは無料ですか?

はい。「calloc と realloc」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。

「calloc と realloc」で何を学びますか?

ゼロ初期化とメモリ拡張です。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「calloc と realloc」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC Academyレッスンでコードを書いて実行できますか?

はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. malloc と free
  2. calloc と realloc
  3. メモリリーク
  4. ダングリングポインター
← C Academyに戻る