いいえ、メモリを 2 回割り当てているわけy->x
ではありません。
代わりに、構造体 (ポインターを含む) にメモリを割り当て、さらにそのポインターが指す何かを割り当てます。
次のように考えてください。
1 2
+-----+ +------+
y------>| x------>| *x |
| n | +------+
+-----+
したがって、すべてを格納するには、実際には 2 つの割り当て (1
と) が必要です。2
さらに、型はstruct Vector *y
ポインターであるため、C からの戻り値をキャストしないでmalloc
ください。隠したくない特定の問題を隠すことができるためです。C は、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);
}
}
このように作成をカプセル化することで、ベクターが完全に構築されているか、まったく構築されていないかを確認できます。また、クライアントに影響を与えることなく、将来的に基礎となるデータ構造を完全に変更することもできます (たとえば、速度のためにスペースをトレードオフするためにそれらを疎な配列にしたい場合)。