112

静的メモリ割り当てと動的メモリ割り当ての違いは何ですか?

これを例で説明できますか?

4

7 に答える 7

133

これは標準的な面接の質問です。

動的メモリ割り当て

calloc()malloc()およびフレンドを使用して実行時に割り当てられるメモリです。ヒープ データ構造refとは関係ありませんが、「ヒープ」メモリと呼ばれることもあります。

int * a = malloc(sizeof(int));

free()が呼び出されるまで、ヒープ メモリは永続的です。つまり、変数の有効期間を制御します。

自動メモリ割り当て

これは一般に「スタック」メモリとして知られているもので、新しいスコープに入ったときに割り当てられます (通常、新しい関数がコール スタックにプッシュされるとき)。範囲外に移動すると、自動メモリ アドレスの値は未定義になり、それらにアクセスするとエラーになります

int a = 43;

スコープは必ずしも機能を意味しないことに注意してください。スコープは関数内でネストでき、変数は宣言されたブロック内でのみスコープ内になります。このメモリが割り当てられる場所は指定されていないことにも注意してください。(正常なシステムでは、スタック上にあるか、最適化のために登録されます)

静的メモリ割り当て

コンパイル時に割り当てられます*。静的メモリ内の変数の有効期間は、プログラムの有効期間です。

staticC では、キーワードを使用して静的メモリを割り当てることができます。スコープはコンパイル単位のみです。

キーワードを考慮するとextern物事はより興味深いものになります。extern変数が定義されると、コンパイラは変数にメモリを割り当てます。extern変数が宣言されている場合、コンパイラは変数を別の場所で定義する必要があります。変数の宣言/定義に失敗するexternとリンクの問題が発生し、変数の宣言/定義に失敗するstaticとコンパイルの問題が発生します。

ファイル スコープでは、 static キーワードはオプションです (関数外)。

int a = 32;

ただし、関数スコープ内ではありません (関数内):

static int a = 32;

技術的には、externstaticは C の変数の 2 つの別個のクラスです。

extern int a; /* Declaration */
int a; /* Definition */

*静的メモリ割り当てに関する注意事項

特に、コンパイル マシンとホスト マシンが同じではないか、同じアーキテクチャ上にない可能性があることを考慮し始めると、コンパイル時に静的メモリが割り当てられると言うのはやや混乱します。

静的メモリの割り当ては、コンパイル時に割り当てられるのではなく、コンパイラによって処理されると考えたほうがよいかもしれません。

たとえば、コンパイラはdataコンパイルされたバイナリに大きなセクションを作成する場合があり、プログラムがメモリにロードされると、dataプログラムのセグメントは、割り当てられたメモリの場所として使用されます。これには、大量の静的メモリを使用する場合、コンパイルされたバイナリが非常に大きくなるという顕著な欠点があります。半ダース未満のコード行から生成された数ギガバイトのバイナリを作成することは可能です。もう 1 つのオプションは、プログラムが実行される前に、別の方法でメモリを割り当てる初期化コードをコンパイラが挿入することです。このコードは、ターゲット プラットフォームと OS によって異なります。実際には、最新のコンパイラはヒューリスティックを使用して、これらのオプションのどれを使用するかを決定します。10k、1m、10m、100m、1G、または 10G 項目の大きな静的配列を割り当てる小さな C プログラムを作成することで、これを自分で試すことができます。多くのコンパイラでは、バイナリ サイズは配列のサイズに比例して増加し続け、特定のポイントを超えると、

登録メモリ

最後のメモリ クラスは「レジスタ」変数です。予想どおり、レジスタ変数は CPU のレジスタに割り当てる必要がありますが、実際の決定はコンパイラに委ねられています。address-of を使用してレジスタ変数を参照に変換することはできません。

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */

最近のほとんどのコンパイラは、どの変数をレジスタに入れるかを選ぶのがあなたよりも賢いです:)

参考文献:

于 2013-04-03T16:37:28.367 に答える
109

割り当てには、静的、自動、および動的の 3 つのタイプがあります。

静的割り当てとは、プログラムの開始時に変数のメモリが割り当てられることを意味します。サイズはプログラム作成時に固定されます。これは、グローバル変数、ファイル スコープ変数、およびstatic定義された内部関数で修飾された変数に適用されます。

自動メモリ割り当ては、関数内で定義された (非静的) 変数に対して発生し、通常はスタックに格納されます(ただし、C 標準ではスタックの使用が義務付けられていません)。それらを使用して追加のメモリを予約する必要はありませんが、一方で、このメモリの有効期間に対する制御も制限されています。例: 関数内の自動変数は、関数が終了するまでしか存在しません。

void func() {
    int i; /* `i` only exists during `func` */
}

動的メモリ割り当ては少し異なります。これらのメモリ ロケーションの正確なサイズと有効期間を制御できるようになりました。解放しないと、メモリ リークが発生し、アプリケーションがクラッシュする可能性があります。これは、ある時点でシステムがより多くのメモリを割り当てることができないためです。

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */

上の例では、関数が終了しても、割り当てられたメモリは有効でアクセス可能です。メモリの使用が終わったら、解放する必要があります。

free(mem);
于 2011-12-05T12:44:08.020 に答える
2

静的メモリ割り当て:コンパイラは、宣言された変数に必要なメモリ空間を割り当てます。演算子のアドレスを使用して、予約されたアドレスを取得し、このアドレスをポインタ変数に割り当てることができます。宣言された変数のほとんどは静的メモリを持っているため、これはポインター変数にポインター値を割り当てる方法は、静的メモリ割り当てとして知られています。メモリはコンパイル時に割り当てられます。

動的メモリ割り当て: malloc( ) や calloc( ) などの関数を使用してメモリを動的に取得します。これらの関数を使用してメモリを動的に取得し、これらの関数によって返される値がポインタ変数に割り当てられている場合、そのような割り当ては動的メモリと呼ばれます。 allocation.memory は実行時に割り当てられます。

于 2011-12-05T14:40:47.037 に答える
2

静的メモリ割り当て:

  • 変数は永続的に割り当てられます
  • 割り当てはプログラム実行前に行われる
  • 静的割り当てを実装するためにスタックと呼ばれるデータ構造を使用します
  • 効率が悪い
  • メモリの再利用性がない

動的メモリ割り当て:

  • プログラム単位がアクティブになった場合にのみ、変数が割り当てられます
  • 割り当てはプログラムの実行中に行われます
  • 動的割り当てを実装するためにヒープと呼ばれるデータ構造を使用します
  • もっと効率的
  • メモリの再利用性があります。不要なときはメモリを解放できます
于 2011-12-05T12:40:01.093 に答える
-1

静的メモリ割り当て。割り当てられたメモリはスタックになります。

int a[10];

動的メモリ割り当て。割り当てられたメモリはヒープになります。

int *a = malloc(sizeof(int) * 10);

C にはガベージ コレクター (GC) がないため、後者はfree d にする必要があります。

free(a);
于 2011-12-05T12:42:33.297 に答える