1. ホーム
  2. c

[解決済み] C 言語の構造体とポインタに対する malloc

2022-03-04 21:08:30

質問

ベクトルの長さを表す構造体とその値を定義したいとします。

struct Vector{
    double* x;
    int n;
};

さて、ベクトルyを定義して、そのためのメモリを確保したいとします。

struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));

ネットで調べると、xのメモリは別に確保したほうがいいようです。

y->x = (double*)malloc(10*sizeof(double));

しかし、y->x用のメモリを確保するときと、y->x用のメモリを確保するときと、2回確保しているようで、メモリの無駄遣いのような気がしています。 コンパイラが実際に何をしているのか、また、どのような方法が正しいのか、教えていただければ幸いです。 yとy->xの両方を初期化します。

よろしくお願いします。

どのように解決するのですか?

いいえ、あなたは ではない のためにメモリを確保する。 y->x を2回実行します。

その代わりに、構造体(ポインターを含む)用のメモリを確保するのです。 プラス そのポインタの指す先となるもの。

このように考えてください。

         1          2
        +-----+    +------+
y------>|  x------>|  *x  |
        |  n  |    +------+
        +-----+

つまり、実際には2つのアロケーションが必要なのです( 12 ) を使ってすべてを格納します。

さらに、あなたのタイプは struct Vector *y からの戻り値をキャストしてはいけません。 malloc を暗黙のうちに変換することができます。 void* の戻り値を他の任意のポインタに変換します。

そしてもちろん、これらのベクターの管理を容易にするために、次のようにベクターの作成をカプセル化したいと思うことでしょう。

struct Vector {
    double *data;    // no place for x and n in readable code :-)
    size_t size;
};

struct Vector *newVector (size_t sz) {
    // Try to allocate vector structure.

    struct Vector *retVal = malloc (sizeof (struct Vector));
    if (retVal == NULL)
        return NULL;

    // Try to allocate vector data, free structure if fail.

    retVal->data = malloc (sz * sizeof (double));
    if (retVal->data == NULL) {
        free (retVal);
        return NULL;
    }

    // Set size and return.

    retVal->size = sz;
    return retVal;
}

void delVector (struct Vector *vector) {
    // Can safely assume vector is NULL or fully built.

    if (vector != NULL) {
        free (vector->data);
        free (vector);
    }
}

このように生成をカプセル化することで、ベクターは完全に構築されるか、まったく構築されないかのどちらかになり、中途半端に構築される可能性はありません。また、クライアントに影響を与えることなく、将来的に基礎となるデータ構造を完全に変更することができます(たとえば、スペースとスピードをトレードオフするために疎な配列にする場合など)。