0Pricing
C Academy · レッスン

配列を確保する

ヒープメモリを確保します。

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

動的配列を使う理由

通常の配列のサイズは、コンパイル時に固定されます。しかし、プログラムの実行が始まるまで必要な要素数がわからないこともよくあります。

動的配列ならこの問題を解決できます。実行時にmallocを使ってオペレーティングシステムにメモリ領域を要求し、変数でサイズを決められます。

mallocを使う

malloc(memory allocate)は<stdlib.h>で使用できます。バイト数を渡すと、その領域へのポインターを返します。失敗した場合はNULLを返します。

メモリはヒープから確保され、解放するまで有効です。

int *p = malloc(10 * sizeof(int));

sizeofでサイズを指定する

バイト数を直接記述してはいけません。sizeofを使えば、どのプラットフォームでも正しく動作するコードにできます。

n個の整数用の領域を確保するには、nにsizeof(int)を掛けます。よく使われる書き方はn * sizeof(*p)で、ポインター自身の型を利用します。

int *p = malloc(n * sizeof(*p));

必ずNULLを確認する

システムのメモリが不足している場合、mallocはNULLを返します。NULLポインターをデリファレンスすると、プログラムがクラッシュします。

使う前に結果を確認してください。この習慣だけで、原因の特定が難しい障害を数多く防げます。

int *p = malloc(n * sizeof(*p));
if (p == NULL) {
    fprintf(stderr, "out of memory\n");
    return 1;
}

完全なメモリ確保

これは、5個の整数分の領域を確保し、値を格納して表示する完全なプログラムです。

mallocで確保を始め、最後にfreeで解放するという対応関係に注目してください。

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

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

mallocはゼロ初期化しない

mallocで確保したメモリは未初期化です。以前そこに入っていた任意の値が残っています。

書き込む前に読み取ると、予測できない値になります。読み取る前に、必ずすべての要素へ値を代入してください。

int *a = malloc(3 * sizeof(*a));
/* a[0], a[1], a[2] hold garbage here */
a[0] = 10;

callocは自動的にゼロ初期化する

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

初期状態がゼロの配列が必要な場合に使います。また、乗算時のオーバーフロー対策にもなります。

int *a = calloc(5, sizeof(*a));
/* every element is now 0 */

callocを使ってみる

このプログラムではcallocを使い、配列がゼロで始まることを確認してから値を変更します。

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

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

領域をインデックスで参照する

ヒープ領域を指すポインターは、配列名とほぼ同じように扱えます。a[i]を使って、0からn-1までの任意の要素を読み書きできます。

内部的には、a[i]は*(a + i)と同じです。

int *a = malloc(3 * sizeof(*a));
a[0] = 1;
*(a + 1) = 2;   /* same as a[1] = 2 */
a[2] = 3;

範囲に注意する

n個の要素を確保した場合、有効なインデックスは0からn-1までです。a[n]への書き込みは未定義動作になります。

Cは範囲を自動的にチェックしないため、1つずれたバグによって、気付かないうちにメモリが破壊されることがあります。

int *a = malloc(3 * sizeof(*a));
a[2] = 99;   /* OK, last valid index */
/* a[3] = 0;  BUG: out of bounds */

実行時にサイズを読み取る

動的配列の本当の強みは、サイズを入力やファイル、計算結果から決められることです。同じコードで、2個でも200万個でも要素を確保できます。

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

int main(void) {
    int n = 6;            /* could be scanf'd */
    long *a = malloc(n * sizeof(*a));
    if (!a) return 1;
    long sum = 0;
    for (int i = 0; i < n; i++) { a[i] = i + 1; sum += a[i]; }
    printf("%ld\n", sum);
    free(a);
    return 0;
}

理解度チェック

メモリ確保について理解できているか確認しましょう。

まとめ

動的配列はmalloc(n * sizeof(*p))で確保でき、calloc(n, sizeof(*p))を使えばゼロで初期化された状態で確保できます。

必ずNULLを確認し、mallocで確保したメモリは未初期化であることを覚えておいてください。インデックスは0からn-1までを使い、確保したメモリは必ずfreeで解放します。次は、データを保持したまま領域のサイズを変更する方法を学びます。

よくある質問

「配列を確保する」レッスンは無料ですか?

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

「配列を確保する」で何を学びますか?

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

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

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

「配列を確保する」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. 配列を確保する
  2. reallocで拡張する
  3. 再利用可能なベクター型
  4. 解放してリークを防ぐ
← C Academyに戻る