メモリには、スタックと呼ばれるセクションがあり、上部から始まり、ヒープに向かって下に成長します。このスタックは LIFO スタックと同じものですか? 一番下のヒープはFIFOですか?
「プッシュ」と「ポップ」を行うと、メモリ内のスタックが変更されますか?
メモリには、スタックと呼ばれるセクションがあり、上部から始まり、ヒープに向かって下に成長します。このスタックは LIFO スタックと同じものですか? 一番下のヒープはFIFOですか?
「プッシュ」と「ポップ」を行うと、メモリ内のスタックが変更されますか?
はい、LIFO スタックはコンピュータ アーキテクチャによって使用され、リターン アドレス、ローカル変数などを保存します。ウィキペディアから:
x86 アーキテクチャには、実行スタック メカニズムのハードウェア サポートがあります。push、pop、call、ret などの命令は、適切にセットアップされたスタックで使用され、パラメーターを渡し、ローカル データにスペースを割り当て、呼び出しリターン ポイントを保存および復元します。ret size 命令は、呼び出し先がパラメーターによって占有されているスタック スペースの再利用を担当する、スペース効率の高い (かつ高速な) 呼び出し規則を実装するのに非常に役立ちます。
たとえば、関数が呼び出されると、アーキテクチャは戻りアドレス、現在のレジスタ値などをスタックにプッシュします。関数が戻ると、そのデータがスタックからポップされるため、実行は前の場所から再開できます。
これはメモリの大きな山ですが、スタックの最上位を指すスタックポインタがあります。プッシュすると上昇し、ポップでは下降します。しかし、多くの場合、ポインタを変更するだけでチートできます。そうすれば、すでにポップされている値を取り戻すことができます。
すべてのアーキテクチャでスタックが同じ方向に進むわけではありません。結局、それはまったく問題ではありません。一部のシステムでは、スタックポインターがプッシュで増加し、ポップで減少します。他のシステムでは、プッシュで減少し、ポップで増加します。
例:スタックポインターは0x100にあり、増加しているシステムです。次にプッシュすると、スタックポインターは0x104になります。0x108でもう一度押します。ポップして、0x104に戻します。もう1つのシステムは、0x100で開始し、0xfcにプッシュダウンしてから、0xf8にプッシュダウンし、0xfcにポップバックします。もう一度ポップすると、0x100に戻ります。次に、スタックポインターから8を引くと、0xf8に戻るので、それらを再度ポップできます。(または、Cコンパイラが関数の最後で行うことは、3つの命令で3つのローカル変数をポップするのではなく、スタックポインタから12を加算/減算するだけです。
「実際にはスタック」(「実際の」スタックとは何ですか?)が何を意味するのかわかりませんが、概念的には同じです。push
「スタックポインター」をデクリメントし、pop
インクリメントします。
あなたが話している「スタック」はプログラムの呼び出しスタックなので、その意味ではスタックです。しかし、そうである必要はありません: 実際の実装は、ハードウェア、OS、および言語ランタイムに固有です — 私はコール スタックがスタック フレームの [二重] リンク リストとして実装され、これは、IBM メインフレーム OS の動作に似ています。
Intel/Windows スタイルの固定サイズのハードウェア スタックの欠点は、環境があまり再帰的ではないことです。OTOH、OSリソースを使用してヒープからメモリを割り当てる必要がないため、スタックの成長が非常に効率的になります。ポインターをインクリメントするだけです。