#include <stdio.h>
int main()
{
int i = 10;
return 0;
}
上記のプログラムでは、正確に値10が格納されていますか?
変数iがスタックに格納されていることを理解しています。スタックは実行時に移入されます。「正確に」10から来ています。
10は定数であるため、コンパイラは、CPU命令の一部として、プログラムの実行可能部分で直接数値10を使用します。
これが私のシステムで作成されたアセンブリですgcc
:
movl $10, -4(%rbp)
(これ4
は、int
が4バイトの長さであるためです)
これらはすべて実装の一部ですが、実際には上記のことが発生することに注意してください。言語自体はこれらの詳細を指定していません。
10
は「リテラル」であり、コンパイル中にコンパイラによって生成されます。そして、それはスタック上の変数に割り当てられます。好き
mov eax, 10;
mov [0x12345678], eax;
これは疑似コードですが、変数i
(アドレスはここでは0x12345678)に10
、以前にに格納されていた値を割り当てますeax
。
「スタック」は、「ヒープ」、グローバル変数、および実行可能コードとは別に、プログラムのオペレーティングシステムによって確保されるメモリの領域です。
関数が呼び出されると、引数をスタックにプッシュするコードがあり、ローカル変数用にスペースが確保されます。関数がこのスペースを返し、すべての引数がスタックから「ポップ」されると、メモリは次の関数で再利用できます。
これは非常に基本的で大まかな説明であり、多くの詳細はシステムとコンパイラーによって異なります。
を設定する明示的なマシンコード命令がありますi
。
何かのようなもの:
MOV AL, 10
実行可能ファイルをコンパイルしてリンクすると、複数のセグメントが含まれます。これらのセグメントの2つのタイプは次のとおりです。
(他のタイプもあります)
値10は、テキストセグメントに格納されるか(10を特定のアドレスまたはレジスタに設定するための命令として)、またはデータセグメントにデータとして格納されます(コードによって取得され、特定のアドレス/レジスタに格納されます)。
コンパイラーは、何が最適かを決定します(指定されたコンパイルフラグに対して最も効率的です)。しかし、値10は「コードで作成」するのが非常に簡単であるため(他のいくつかの回答で示されているように)、テキストセグメントに「格納」されていると思います。
より複雑なデータ(構造体、文字列など)は、通常、データセグメントに格納されます。
値10は、ソースコードを含む物理ソースファイルに保存されます。i
実行中に、その値は、自動保存期間があり、タイプが。であるという名前の変数に転送されますint
。重要なのはそれだけです。それ以上の質問は、Cなどの汎用プログラミング言語の領域では生産的ではありません。
ほとんどの回答がコンパイラについて言及していることに注意してください。インタプリタを使用してCソースコードを直接動作に変換するとどうなりますか?これらの答えはまだ有効ですか?
あなたがそうするなら、私はむしろ「人に魚を与える」のではありません...あなたは実際にそれを自分でチェックすることができます:
コードを取り出して、そこからオブジェクトファイルを作成します。
> gcc -c file.c -o file.o
次に、生成されたファイルに対してオブジェクトダンプを実行します。
> objdump -d file.o
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: c7 45 fc 0f 00 00 00 movl $0xa,-0x4(%rbp) // Right here you can see
// the raw value 0xa (10)
// being set, so it's in the
// .text section