谁调了main函数

之前思考过一个问题:为什么C语言要有main函数,而且程序从main函数开始执行,查了一下资料,以下是我整理的一些内容。

C语言为什么要有main函数

之前写时 shell 脚本,发现 shell 直接将源程序写在源文件中,然后就从头至尾就开始执行了,并没有像 C语言那样需要一个 main 函数,然后程序从 main 函数开始执行。实际上大多数的脚本语言都是这样——并不需要注明程序执行的开始位置。

我们知道 C程序从编写到执行要经过:预处理——编译——链接 几个阶段,每个编辑单元(.c 文件)都是独立生成自己的目标文件(.o 文件),最后由链接器将这些目标文件链接到一起,生成可执行文件,在该期间,可能还会链接一些库文件。

对于多个编辑单元,链接器需要知道程序的入口在哪里,于是就利用函数不能重复定义的机制,规定程序的入口函数为 main 函数,如果一个程序中超过一个入口函数,编译器就会报错。

没有main函数行不行

事实上,C语言程序不一定非得有main函数。
C语言标准在一开始(C90标准 5.1.2条),就规定了程序的执行环境。
对于没有操作系统的环境来说,C程序的入口函数是什么都可以(也就是说的在单片机的C程序里,或者在操作系统的底层代码的C入口处,不需要是main函数)。对于有操作系统的环境来说,C程序的入口是main函数。而且被声明为以下两者其中之一:

int main(void);
int main(int argc, char * argv[]);
谁调了main函数

我们先看看如果C程序没有买呢函数会怎样:

#include <stdio.h>
int nomain()
{
    printf("Hello World.\n");
    return 0;
}

结果如下:
这里写图片描述

没有main函数时,程序编译的结果是:在函数 _start 中使用了未定义的 main 函数,这说什么?说明是 start 函数调用了 main 函数,实际上 start 函数是操作系统开始执行C程序的起点。
我们再来看个例子确认一下:
这里写图片描述

参数 nostdlib 表示不使用标准库,我们加上该参数编译时,编译器告诉我们,找不到符号 _start,这也就说明了 _start 函数是操作系统执行C程序的起点。

main函数被调之前和之后

我们写的C程序一开始就可以使用:stdin、stdout、stderr,这些标准流是什么时候打开的呢,main函数的栈帧空间是谁初始化的呢?
通常,我们会在编译器的环境中找到一个名字类似于 crt0.o 的文件,这个文件中包含了我们刚才所说的 __start 符号。(crt 大概是 C Runtime 的缩写),crt0里面都干了些什么呢?如下:

//伪代码
 section .text:
    __start:
    
     :
     init stack;// 初始化栈
     init heap;//初始化堆
     open stdin;//打开标准输入
     标准输出、标准错误三个流
     open stdout;
     open stderr;
     :
     push argv;//传递main函数的参数
     push argc;
     call _main; //调用 main
     :
     return 0//从main函数返回
     destory heap;//清理工作
     close stdin;
     close stdout;
     close stderr;
     :
     call __exit;

——完!

参考内容
- https://www.zhihu.com/question/28360770
- http://blog.sina.com.cn/s/blog_4b34c6790100lqvc.html

【作者:果冻 http://blog.csdn.net/jelly_9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值