找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2335|回复: 12

C语言种的main()函数有好几种类型,系统是这样调用它的

 火.. [复制链接]
  • 打卡等级:常驻代表
  • 打卡总天数:34
  • 打卡月天数:6
  • 打卡总奖励:9027
  • 最近打卡:2025-12-17 23:15:51

2823

主题

541

回帖

2万

积分

管理员

积分
22569
发表于 2021-3-2 21:18:48 | 显示全部楼层 |阅读模式
​基本上,几乎每一个初学者在刚接触C语言时,都会被告知C语言程序的默认入口是 main() 函数,程序总是从入口函数处开始运行。一般来说,main() 函数有两个常用的原型,它们的C语言代码是下面这样的:
int main();int main(int argc, char *argv[]);

为什么在C语言程序中,可以有不同类型的 main() 函数呢?


当然,在一些比较旧的教材或者C语言代码中,读者可能还见过 void 返回值类型,甚至没有写返回值类型的 main() 函数原型:
void main();main();
C++程序基本上也是如此,但是 C++ 提供了重载语法支持,因此同一个函数具有不同的参数类型是可以理解的。而C语言没有重载语法,为什么在C语言程序中,可以有不同类型的 main() 函数呢?
专栏

C语言经典面试题目详解
作者:嵌入式时代
26.6币
133人已购

查看




为什么在C语言程序中,可以有不同类型的 main() 函数呢?
C语言程序支持多种类型 main() 函数,其实和支持可变参数函数是类似的。按照我之前文章中的讨论,对于可变参数函数,例如 printf() 函数,或者未明确指定参数的函数,例如 void fun(); ,在被调用时,是允许传入任意多参数的:
printf("...");printf("...%d", 666);fun();fun(1, 2, 3, 4);
上面几行C语言代码都是合法的。一般来说,C语言代码被编译为指令后,函数被调用时,它的参数是按照顺序入栈的——要么是从最左参数依次入栈,要么是从最右参数依次入栈,函数执行完毕后,再依次出栈。下面是一段示例指令:

示例指令


这时再来看C语言程序中的几种 main() 函数类型就简单了,如果 main() 函数时没有传递参数:
int main(){ ...}
那么系统直接忽略参数栈就可以了。如果某段C语言程序中的 main() 函数有两个参数:
int main(int argc, char *argv[]){ ...}
那么系统就会将 argc 和 argv 作为栈顶的两个元素,最后在 main() 函数执行完毕后,将参数从栈中弹出就可以了。
专栏

手把手教你学LinuxC语言编程
作者:嵌入式时代
49.9币
129人已购

查看




按照这种思路,我们甚至可以定义具有三个参数的 main() 函数,下面是一段C语言代码示例:
#include <stdio.h>void fun(int a, int b){ printf("a=%d, b=%d\n", a, b);}int main(int a, char **b, char **c){ fun(2, 3); return 0;}

C语言代码示例


编译并执行这段C语言代码,可以得到如下输出:
# gcc t.c# ./a.out a=2, b=3
这是容易理解的,因为处理三个参数的 main() 函数时,系统无非就是多做一些参数入栈和出栈的操作而已。如果某个平台需要使用 main() 函数的第三个参数(有些平台使用 main() 函数的第三个参数作为环境指针),它只需从堆栈顶部找到第三个元素就可以了。
这种情况下,类似的C语言代码是下面这样的:
extern int main(int argc, char **argv, char **envp);void __start(void){ /* ... */ exit( main(argc_from_somewhere,  argv_from_somewhere,  envp_from_somewhere));}
其实到这里,读者应该能明白了,C语言程序中的 main() 函数调用其实就是“约定”,只要 main() 函数不关心它的调用者传递的参数,那么传什么样的参数给 main() 都是可以得到正常工作的C语言程序的。

C语言程序中的 main() 函数调用其实就是“约定”


最后
还有一种情况需要说明,如果某段C语言程序中的 main() 函数是下面这样的,明确指定 main() 函数没有参数:
int main(void){ ...}
编译器可能会将其做特殊处理——执行一个代码转换,最后实际的 main() 函数实际上是下面这样的:
int main(int __argc_ignore, char **__argv_ignore, char **__envp_ignore){ /* ... */}
也有可能编译器会从几种预编译的备选方案中选择一种支持C语言程序定义的 main() 函数,这种方法也是可行的。

点个赞再走吧


欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。
来源:IT刘小虎(头条)

工控课堂 www.gkket.com

0

主题

77

回帖

147

积分

新手上路

积分
147
发表于 2021-3-2 21:18:50 | 显示全部楼层
好东西一定要看看!
工控课堂 www.gkket.com

0

主题

100

回帖

274

积分

注册会员

积分
274
发表于 2021-3-4 16:44:45 | 显示全部楼层
这个类目最活跃了!赞一个!
工控课堂 www.gkket.com

0

主题

130

回帖

348

积分

注册会员

积分
348
发表于 2025-11-17 03:24:43 | 显示全部楼层
楼主辛苦啦,期待下一篇分享
工控课堂 www.gkket.com

0

主题

118

回帖

407

积分

注册会员

积分
407
发表于 2025-11-17 03:56:05 | 显示全部楼层
来凑个热闹,为楼主增加点人气!
工控课堂 www.gkket.com

0

主题

111

回帖

164

积分

新手上路

积分
164
发表于 2025-11-17 06:52:40 | 显示全部楼层
楼主太会说了,字字句句都在理
工控课堂 www.gkket.com

0

主题

423

回帖

2733

积分

高级会员

积分
2733
发表于 2025-11-17 15:00:30 | 显示全部楼层
求个链接 / 教程,楼主好人一生平安~
工控课堂 www.gkket.com

0

主题

101

回帖

154

积分

新手上路

积分
154
发表于 2025-11-17 16:54:13 | 显示全部楼层
赞同 + 10086,完全说出了我的想法!
工控课堂 www.gkket.com

0

主题

79

回帖

120

积分

新手上路

积分
120
发表于 2025-11-17 16:56:04 | 显示全部楼层
哈哈哈哈笑不活,楼主这脑洞绝了!
工控课堂 www.gkket.com

0

主题

67

回帖

85

积分

新手上路

积分
85
发表于 2025-11-17 17:19:59 | 显示全部楼层
同款经历!简直是世另我
工控课堂 www.gkket.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|手机版|免责声明|本站介绍|工控课堂 ( 沪ICP备20008691号-1 )

GMT+8, 2025-12-23 04:21 , Processed in 0.097961 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表