0Pricing
C Academy · レッスン

再利用可能なベクター型

サイズと容量をまとめて扱います。

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

ばらばらのコードから型へ

ポインター、要素数、容量を3つの別々の変数としてあちこちに渡す方法は、エラーの原因になります。

これらを1つのstructにまとめましょう。これは再利用可能な動的配列で、一般にベクターと呼ばれます。データと管理情報を一緒にまとめて扱えます。

ベクターのstruct

ベクターには3つのフィールドが必要です。データへのポインター、使用中の要素数(len)、そしてサイズ変更前に収容できる要素数(cap)です。

typedef struct {
    int    *data;
    size_t  len;
    size_t  cap;
} Vec;

ベクターの初期化

空のベクターでは、データポインターがNULLで、長さと容量がともに0です。短いinit関数を用意すると、意図が明確になります。

void vec_init(Vec *v) {
    v->data = NULL;
    v->len = 0;
    v->cap = 0;
}

push操作

vec_pushは末尾に要素を1つ追加します。ベクターが満杯の場合は、先に容量を2倍にします。

成功時には0を返し、メモリ確保に失敗した場合は-1を返すため、呼び出し側で対処できます。

int vec_push(Vec *v, int value) {
    if (v->len == v->cap) {
        size_t nc = v->cap ? v->cap * 2 : 4;
        int *tmp = realloc(v->data, nc * sizeof(*v->data));
        if (!tmp) return -1;
        v->data = tmp;
        v->cap = nc;
    }
    v->data[v->len++] = value;
    return 0;
}

要素を読み出す

lenが使用中の要素数を記録しているため、0からlen - 1まで反復します。容量のほうが大きい場合もありますが、そのスロットはまだデータの一部ではありません。

for (size_t i = 0; i < v->len; i++)
    printf("%d\n", v->data[i]);

ベクターの解放

ベクターはヒープバッファを所有しているため、それに対応する解放関数が必要です。解放後はフィールドをリセットし、structが誤って使われないようにします。

void vec_free(Vec *v) {
    free(v->data);
    v->data = NULL;
    v->len = v->cap = 0;
}

全体を組み立てる

この完全なプログラムでは、ベクターを作成し、5つの値を追加して表示した後、適切に解放します。

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

typedef struct { int *data; size_t len, cap; } Vec;

int vec_push(Vec *v, int value) {
    if (v->len == v->cap) {
        size_t nc = v->cap ? v->cap * 2 : 4;
        int *tmp = realloc(v->data, nc * sizeof(*v->data));
        if (!tmp) return -1;
        v->data = tmp; v->cap = nc;
    }
    v->data[v->len++] = value;
    return 0;
}

int main(void) {
    Vec v = {0};
    for (int i = 0; i < 5; i++) vec_push(&v, i * 10);
    for (size_t i = 0; i < v.len; i++) printf("%d\n", v.data[i]);
    free(v.data);
    return 0;
}

{0}によるゼロ初期化

Vec v = {0};と記述すると、データポインターをNULLにすることも含め、すべてのフィールドが0に設定されます。

これは便利な省略記法で、明示的なinit関数を呼び出さなくても、ベクターをvec_pushで使える状態にできます。

Vec v = {0};      /* data=NULL, len=0, cap=0 */
vec_push(&v, 42);

安全なgetヘルパー

lenを超えた位置へのインデックスアクセスはバグです。小さなアクセサーで境界を確認し、エラーを通知できます。速度を少し犠牲にして安全性を高める方法です。

int vec_get(const Vec *v, size_t i, int *out) {
    if (i >= v->len) return -1;   /* out of range */
    *out = v->data[i];
    return 0;
}

lenとcapを別々に管理する理由

capは確保済みのメモリ容量であり、lenは実際に使用している量です。

余分な容量を確保しておけば、ほとんどのpushでreallocを呼び出さずに済みます。この分離によって、ベクターは高速かつ柔軟になります。

型を一般化する

このベクターはintを格納します。他の型を格納するには、要素型を変更するか、要素サイズとともにvoid *を格納します。

格納するものが何であっても、パターン、init、push、freeは変わりません。

typedef struct {
    double *data;
    size_t  len, cap;
} DVec;   /* same shape, different element type */

クイックチェック

ベクター型についての理解度を確認しましょう。

まとめ

ベクターは、データポインター、len、capを1つのstructにまとめます。

満杯になるとvec_pushは容量を2倍にし、vec_freeはバッファを解放してフィールドをリセットします。また、{0}で適切に初期化できます。この再利用可能なパターンは、ばらばらの変数を個別に管理するより優れています。次は、正しく解放してリークを避ける方法です。

よくある質問

「再利用可能なベクター型」レッスンは無料ですか?

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

「再利用可能なベクター型」で何を学びますか?

サイズと容量をまとめて扱います。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「再利用可能なベクター型」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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