程序执行是不是总是从 C 中的 main 开始?
Posted
技术标签:
【中文标题】程序执行是不是总是从 C 中的 main 开始?【英文标题】:Does the program execution always start from main in C?程序执行是否总是从 C 中的 main 开始? 【发布时间】:2011-08-01 11:29:55 【问题描述】:程序执行必须从main开始,还是可以修改起始地址?
#include <stdio.h>
void fun();
#pragma startup fun
int main()
printf("in main");
return 0;
void fun()
printf("in fun");
这个程序在in main
之前打印in fun
。
【问题讨论】:
How do you use pragma startup preprocessor? 的可能重复项 【参考方案1】:“#pragma”命令在 ANSI 标准中被指定为具有任意实现定义的效果。在 GNU C 预处理器中,'#pragma' 首先尝试运行游戏'rogue';如果失败,它会尝试运行游戏“hack”;如果失败,它会尝试运行显示河内塔的 GNU Emacs;如果失败,它会报告一个致命错误。在任何情况下,预处理都不会继续。
-- Richard M. Stallman,GNU C 预处理器,1.34 版
程序执行从启动代码或“运行时”开始。这通常是一些名为_start
或类似的汇编程序,位于(在Unix 机器上)编译器包附带的文件crt0.o
中。它执行运行 C 可执行文件所需的设置(例如,设置 stdin
、stdout
和 stderr
,atexit()
使用的向量...对于 C++ 它还包括初始化全局对象,即运行它们的构造函数)。只有这样控制才会跳转到main()
。
正如我的答案开头的引述如此雄辩地表达的那样,#pragma
所做的完全取决于您的编译器。检查其文档。 (我猜你的pragma startup
- 顺便说一句,应该在前面加上#
- 告诉运行时首先调用fun()
...)
【讨论】:
实际上,我希望编译器构建者能够坚持 Stallman 的立场。它将使我们免于诸如pragma once
或源代码硬禁用编译器警告之类的愚蠢事情...【参考方案2】:
就 ISO C 标准而言,C 程序的入口点始终是 main
(除非使用某些实现定义的特性来覆盖它)对于托管实现。对于“独立实现”(通常是嵌入式系统,通常没有操作系统),入口点是实现定义的。
【讨论】:
【参考方案3】:C 程序不一定从main()
函数开始。一些代码在main()
之前执行,将所有未初始化的全局变量清零并用适当的值初始化其他全局变量。例如,考虑以下代码:
int a;
int b = 10;
int main()
int c = a * b;
return 0;
在上面的示例代码中,a
和 b
在执行main()
的第一行之前分别分配了0
和10
。
#pragma
指令用于定义实现定义的行为。您带有#pragma
的代码可能会在某些编译器中编译,但可能无法在其他编译器中编译。
【讨论】:
.data 和 .bss 部分的设置不是由可执行加载器完成的,而不是由启动代码完成的吗? @devsolar:情况可能并非总是如此。例如微控制器。我曾在 OKI 411、OKI 431 和 PIC16F 微控制器上工作过。它们都有某种启动/运行时代码。顺便说一句,我不知道这些在为 PC 编程时是如何实现的。我只听说过.data
和.bss
这两个名字,不太了解。你能给我一些链接,我可以从中了解更多信息吗?
基本 ELF 对象文件布局: .text 部分包含机器代码, .data 包含初始化数据(您的示例中的 10
)。 .bss 是“零初始化”区域,它当然不在可执行文件中,或者只是作为“大小”数字;您将其留给加载程序以提供足够的零初始化内存。当然,现实更加困难(包含调试信息或 C++ 异常处理或类似内容的部分)。检查***,“数据段”。以上是关于程序执行是不是总是从 C 中的 main 开始?的主要内容,如果未能解决你的问题,请参考以下文章
请教各位大侠C++中程序在开始main()函数之前的执行顺序是怎么样的?