根据我们的书,每个函数在C中的运行时堆栈中都有一个激活记录。每个激活记录都有一个返回地址,动态链接和返回值。主要还有这些吗?
答案 0 :(得分:5)
所有这些术语都是纯粹的实现细节--C没有“返回地址”或“动态链接”的概念。它根本没有“堆叠”的概念。 C的大多数实现都包含这些对象,在这些实现中,它们可能存在于main
中。但是,并不要求发生这种情况。
希望这有帮助!
答案 1 :(得分:2)
如果您反汇编函数,您将意识到堆栈甚至不包含返回值的大部分时间 - 通常是EAX寄存器(intel x86)。 您还可以查找“调用约定” - 这几乎取决于编译器。 C是一种语言,如何将其解释为机器代码并不是“它的”业务。
答案 2 :(得分:0)
虽然这取决于实现,但值得看一下用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 base文档,您会发现我们从__libc_start_main
看到的对_start
的调用实际上需要main
表现得像常规函数
答案 3 :(得分:-1)
在C / C ++中,main()
就像一个函数一样编写,但不是一个函数。例如,不允许调用main()
,它有几个可能的原型(在C中不能这样做!)。无论return
是什么,它都会被传递给操作系统(并且程序结束)。
单个C实现可能会处理main()
,就像从“外部”调用的函数一样,但是没有人强迫它们这样做(或者不允许切换到其他形式的操作而不告诉任何人)。有传统的实现C的方法,但没有人被迫这样做。这是我们典型架构中最简单的方法。