私たちの本によると、各関数は C のランタイム スタックにアクティベーション レコードを持っています。これらのアクティベーション レコードにはそれぞれ、戻りアドレス、動的リンク、および戻り値があります。メインにはこれらもありますか?
4 に答える
これらの用語はすべて純粋に実装の詳細です。C には「リターン アドレス」や「動的リンク」という概念はありません。「スタック」の概念すらありません。C のほとんどの実装には、これらのオブジェクトが含まれており、これらの実装では、オブジェクトが存在する可能性がありmain
ます。ただし、これが発生する必要はありません。
お役に立てれば!
関数を逆アセンブルすると、ほとんどの場合、スタックには戻り値さえ含まれていないことがわかります。多くの場合、EAX レジスタが含まれています (intel x86)。「呼び出し規約」を調べることもできます - それはすべてほとんどコンパイラに依存します. C は言語であり、機械語にどのように解釈されるかは「その」仕事ではありません。
これは実装に依存しますが、gcc でコンパイルされた C プログラムを見る価値があります。を実行すると、分解されて がどのように動作するobjdump -d executable
かがわかります。main()
次に例を示します。
08048680 <_start>:
...
8048689: 54 push %esp
804868a: 52 push %edx
804868b: 68 a0 8b 04 08 push $0x8048ba0
8048690: 68 30 8b 04 08 push $0x8048b30
8048695: 51 push %ecx
8048696: 56 push %esi
8048697: 68 f1 88 04 08 push $0x80488f1
804869c: e8 9f ff ff ff call 8048640 <__libc_start_main@plt>
80486a1: f4 hlt
...
080488f1 <main>:
80488f1: 55 push %ebp
80488f2: 89 e5 mov %esp,%ebp
80488f4: 57 push %edi
80488f5: 56 push %esi
80488f6: 53 push %ebx
...
8048b2b: 5b pop %ebx
8048b2c: 5e pop %esi
8048b2d: 5f pop %edi
8048b2e: 5d pop %ebp
8048b2f: c3 ret
main が正常に戻るという点で、通常の関数と同様に動作することがわかります。実際、Linux ベースのドキュメントを見ると、__libc_start_main
そこから見た への呼び出しが_start
実際にはmain
通常の関数のように動作する必要があることがわかります。
C / C ++では、main()
関数と同じように記述されていますが、関数ではありません。たとえば、呼び出すことは許可されてmain()
いません。いくつかの可能なプロトタイプがあります(Cではそれを行うことはできません!)。それからreturn
編集されたものはすべてオペレーティングシステムに渡されます(そしてプログラムは終了します)。
個々のC実装はmain()
、統一性のために「外部」から呼び出される関数のように処理できますが、誰も強制的にそうすることはありません(または、誰にも言わずに他の形式に切り替えることを禁止します)。Cを実装する従来の方法はありますが、その方法を強制されることはありません。これは、私たちの典型的なアーキテクチャで最も簡単な方法です。