main函数执行前编译器做了什么?
main函数执行前编译器做了什么?
编译器做了什么
编译器在编译一个工程时,默认的程序入口是_start符号,而不是main。符号main是一个约定的符号,它用来告诉编译器在一个项目中哪里是程序的入口点。程序员在开发一个项目时,也会遵守这个约定,使用main()函数作为项目的入口函数。
兵马未动,粮草先行。其实在main()函数运行之前,已经有“先头部队”代码提前运行了:它们主要完成运行main()函数前的一些初始化工作,如初始化堆栈指针等。
初始化:堆/栈/指针
栈是C语言运行的必备环境,C语 言函数调用过程中的参数传递、函数内部的局部变量都是保存在栈中 的。没有栈C语言就无法运行,因此在运行main()函数之前必须先运行一段汇编代码来初始化堆栈环境。
初始化:其他环境
设置好堆栈指 针后,这部分代码还要继续初始化一些环境:
-
初始化data段
1.1 初始化static变量
1.2 初始化global全局变量 -
给BSS段的变量赋初值
-
未初始化的变量给定默认值,如 int = 0;bool = false;指针 = NULL。
将未初始化部分的赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL,等等,即.bss段的内容
所有初始化操作清单
- C语言运行的基本堆栈环境、进程环境。
- 动态库的加载、释放、初始化、清理等工作。
- 向main()函数传参argc、argv,调用main()函数执行。
- 在main()函数退出后,调用exit()函数,结束进程的运行。
跳入main()函数执行
完成初始化环境后, 这部分代码还会将用户传入的参数传递给main,最后才跳入main()函
数运行。
这部分初始化代码是在程序编译阶段,由编译器自动添加到可执 行文件中的。
这部分代码属于C运行库(C Running Time,CRT)中的 代码,编译器厂商在开发编译器时,除了实现C语言标准中规定的printf、fopen、fread等标准函数,还会实现这部分初始化代码,完成进入main()函数之前的一系列初始化操作。