[解決済み] C 言語の構造体とポインタに対する malloc
質問
ベクトルの長さを表す構造体とその値を定義したいとします。
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つのアロケーションが必要なのです(
1
と
2
) を使ってすべてを格納します。
さらに、あなたのタイプは
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);
}
}
このように生成をカプセル化することで、ベクターは完全に構築されるか、まったく構築されないかのどちらかになり、中途半端に構築される可能性はありません。また、クライアントに影響を与えることなく、将来的に基礎となるデータ構造を完全に変更することができます(たとえば、スペースとスピードをトレードオフするために疎な配列にする場合など)。
関連
-
[解決済み】 `S_ISREG()` とは何ですか、そして何をするのですか?
-
[解決済み】ポインタへの代入時に互換性のないポインタ型からの初期化警告が発生した
-
[解決済み】 strcpyとstrdupの比較
-
[解決済み] '{'トークンの前に期待される式
-
[解決済み] JVM起動時のパラメータ「-Xms」「-Xmx」とは何ですか?
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] mallocの結果はキャストするのですか?
-
[解決済み] mallocとcallocの違い?
-
[解決済み] 8192個の要素にループをかけると、プログラムが遅くなるのはなぜですか?
-
[解決済み] malloc/free/new/deleteでコンパイラがメモリを0xCDや0xDDなどに初期化するのはいつ、なぜですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Cコンパイルエラー。"変数サイズのオブジェクトが初期化されていない可能性がある"
-
[解決済み】Cコンパイルエラーです。Idは1終了ステータスを返した
-
[解決済み】C言語におけるファイルスコープでの可変長配列の変更
-
[解決済み】ポインタへの代入時に互換性のないポインタ型からの初期化警告が発生した
-
[解決済み】スレッド1:EXC_BAD_ACCESS(コード=1、アドレス=0x0)標準Cメモリ問題
-
[解決済み】ヒープ割り当てで初期化されていない値が作成された
-
[解決済み】MB/sとMiB/sを計算する方法は?
-
[解決済み】argv[]をint型として取得するには?
-
[解決済み】malloc():メモリ破壊
-
[解決済み】execvp: バッドアドレスエラー