[解決済み] スタックは上に伸びるのか、下に伸びるのか?
質問
C言語でこのようなコードがあります。
int q = 10;
int s = 5;
int a[3];
printf("Address of a: %d\n", (int)a);
printf("Address of a[1]: %d\n", (int)&a[1]);
printf("Address of a[2]: %d\n", (int)&a[2]);
printf("Address of q: %d\n", (int)&q);
printf("Address of s: %d\n", (int)&s);
と出力されます。
Address of a: 2293584
Address of a[1]: 2293588
Address of a[2]: 2293592
Address of q: 2293612
Address of s: 2293608
ということで、なるほど
a
から
a[2]
というように、メモリアドレスが4バイトずつ増えていきます。
しかし
q
から
s
となり、メモリアドレスが4バイト分減少します。
2つ疑問があります。
- スタックは上に伸びるのか、下に伸びるのか?(この場合、私には両方に見えます。)
-
の間に何が起こりますか?
a[2]
とq
というメモリアドレスがあります。なぜそこに大きなメモリの違いがあるのでしょうか?(20バイト)です。
注:これは宿題のような質問ではありません。私はスタックがどのように動作するかについて興味があります。どんな助けでもありがとうございます。
どのように解決するのですか?
スタックの動作 (グロウアップまたはグロウダウン) は、アプリケーション バイナリ インターフェイス (ABI) とコール スタック (別名アクティベーション レコード) がどのように構成されているかに依存します。
プログラムはそのライフタイムを通じて、OS のような他のプログラムと通信するよう束縛されます。ABI は、プログラムが他のプログラムとどのように通信できるかを決定します。
異なるアーキテクチャのスタックはどちらにも成長できますが、あるアーキテクチャでは一貫しています。以下を参照してください。 この wiki のリンクを参照してください。しかし、スタックの成長は、そのアーキテクチャのABIによって決まります。
例えば、MIPSのABIを例にとると、コールスタックは以下のように定義されています。
関数'fn1'が'fn2'を呼び出すことを考えてみましょう。ここで、'fn2'から見たスタックフレームは次のようになります。
direction of | |
growth of +---------------------------------+
stack | Parameters passed by fn1(caller)|
from higher addr.| |
to lower addr. | Direction of growth is opposite |
| | to direction of stack growth |
| +---------------------------------+ <-- SP on entry to fn2
| | Return address from fn2(callee) |
V +---------------------------------+
| Callee saved registers being |
| used in the callee function |
+---------------------------------+
| Local variables of fn2 |
|(Direction of growth of frame is |
| same as direction of growth of |
| stack) |
+---------------------------------+
| Arguments to functions called |
| by fn2 |
+---------------------------------+ <- Current SP after stack
frame is allocated
これでスタックが下に伸びていくのがわかると思います。つまり、変数が関数のローカルフレームに割り当てられると、変数のアドレスは実際に下に伸びていくのです。コンパイラはメモリ割り当ての際の変数の順番を決めることができます。(あなたの場合、最初にスタックメモリを割り当てるのは 'q' か 's' のどちらかです。しかし、一般的にコンパイラは変数の宣言の順番通りにスタックメモリを割り当てる)。
しかし、配列の場合、割り当てにはシングルポインタしかなく、割り当てられる必要があるメモリは実際にはシングルポインタによって指されます。配列の場合、メモリは連続である必要があります。そのため、スタックは下に伸びていきますが、配列の場合は上に伸びていきます。
関連
-
C++の配列コピー
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] 配列のすべてのメンバーを同じ値で初期化するには?
-
[解決済み] JavaScriptでStackとQueueを実装するには?
-
[解決済み] C言語で関数をパラメータとして渡すにはどうすればよいですか?
-
[解決済み] なぜJavaのVector(およびStack)クラスは時代遅れ、または非推奨とされているのですか?
-
[解決済み] どちらが速いですか?スタックアロケーションとヒープアロケーション
-
[解決済み】ベースポインタとスタックポインタとは一体何でしょうか?これらは何を指しているのでしょうか?
最新
-
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 実装 サイバーパンク風ボタン