配列を次のように宣言するとします。 int myarray[5]
またはそれを次のように宣言しますint*myarray=malloc(5*sizeof(int))
両方の宣言は、バイト数で同じ量のメモリを設定しますか? 前者の宣言がスタック用であり、後者がヒープ用であることを考慮せずに。
ありがとうございました!
基本的な違いがありますが、使用 方法では明らかではない場合がありますmyarray
。
int myarray[5];
5 つの整数の配列を宣言し、配列は自動変数です (初期化されていません)。
int * myarray = malloc(5 * sizeof(int));
int へのポインターである変数を (自動変数としても) 宣言し、そのポインターはライブラリ呼び出しの結果で初期化されます。そのライブラリ呼び出しは、結果のポインターが 5 つの連続した整数を格納するのに十分な大きさのメモリ領域を指すようにすることを約束します。
ポインター演算、配列からポインターへの減衰、および と同じ規則によりa[i]
、*(a + i)
両方の変数を同じ方法で、つまり として使用できますmyarray[i]
。これはもちろん設計によるものです。
違いを探している場合は、次の方法が役立つかもしれません: 5 つの整数の配列は単一のオブジェクトであり、サイズが決まっています。対照的に、malloc
ライブラリ呼び出しはオブジェクトを作成しません。十分なメモリを確保する(そして適切に配置する) だけですが、たとえば、より多くのメモリを割り当てることができます。
(C++ ではもちろん、メモリとオブジェクトの間に追加の区別があります。)
どちらも正確に5*sizeof(int)
バイトを割り当てることは保証されていませんが、どちらも少なくともそれだけのスペースを提供します (割り当ての失敗やスタックの枯渇がないことを前提としています)。
最初のケースでは、スタック変数はアラインメント パディングやスタック カナリア (コンパイル オプションによって異なります) で囲まれている可能性があります。これらにより、スタック ポインターが5*sizeof(int)
バイト単位で調整される可能性があります。
int *
2 番目のケースでは、スタック (sizeof(int *)
バイト) に加えて、返されるスペースを割り当てmalloc
ます。malloc
は、割り当て追跡構造、アラインメント パディング、リンク リスト ポインタなどの形式で追加のメモリを割り当てる場合があります。したがって、その場合、正確に5*sizeof(int)
バイトを割り当てることも保証されません。
メモリ使用量を正確に把握したい場合は、mmap
関数を使用して OS から仮想メモリのページを要求できます。この方法で要求するメモリは、正確に要求した量になります (これらの割り当てを追跡するためにカーネルで使用されるスペースは無視します)。
短い答え: いいえ、通常、後者は小さな大きなメモリを使用します。
長い答え: メモリ管理は、返されたポインタを管理し、それを追跡し、後で解放できるようにするために、確かに追加のメモリを使用します。そのメモリを指す追加のポインタを宣言します。したがって、その実際のメモリはsizeof(int*) + malloc_overhead
. ただし、最初のケースでは、正確に 5 int を使用します (プラスの配置も可能です)。
動的割り当てには、少なくとも数バイトの余分なバイトが必要です。ただし、 5 サイズの要素に加えてポインター変数用に多くのバイトが必要int
であり、割り当てられた領域のサイズを追跡してfree
適切に d できるようにするために余分なバイトが必要になる可能性があります。