C语言必须写main函数?最简单的 Hello world 你其实一点都不懂!

我们在刚写程序的时候,第一个都是 hello world,而在这里,完整的代码就是:

我们打眼一看,其实很简单,就是引入头文件,写一个主函数,然后输出一句话,但是当我们编译出来ELF的时候,我们使用工具readelf,去查看下这里面的FUNC,会发现多了很多方法。(gcc相关工具链,我经常用的是objdump )

如果你想知道这个过程都处理了什么,可以使用gcc -o hello hello.c -v,这里的-v,会输出过程信息,这里截一部分,大家看下

这块要学习,去GCC官方看下它的编译,链接参数。Makefile文件,可以使用 --just-print 进行调试。这里面的UND,代表的是未定义,未定义的这些方法,会在加载器加载的时候,补充进来。

我们这里使用 IDA 来解析下这个输出ELF,可以看到一个简单的信息。

这里的Interpreter,就是解析程序,crtstuff.c这个就是给我们的运行环境,做初始化。从这里我们就能看到,其实我们的一个简单的程序,也是五脏俱全的。

既然它们的流程是,系统加载进来,然后初始化,再到我们的main方法,那么这个main方法,肯定是可以变的。为什么这么说呢?做过嵌入式开发的应该熟悉,基本上都没有main函数一说,直接从跳转入口开始跑就可以的。可以给任意函数,指定成Enter,也就是入口函数,使用链接脚本就可以指定,这块感兴趣的可以搜索gcc链接器参数。

我们先简单做一个操作,这样子来处理下。gcc -o hello hello.c -nostdlib

我们来把这个库去掉,看看会报哪些错误,可以看到这里报了入口点找不到,也就是_start 。

https://my.oschina.net/saly/blog/130920 我们看下这里的参数介绍:

我们是用gcc -o hello hello.c -nostartfiles 把这个启动函数去掉,然后我们自己实现一个。然后我们把文件修改成

这里修改成exit ,同时加上对应的库文件,去掉return的原因是,这时候不能返回,需要清理,返回去没人接这个,系统中使用的是jmp,你返回就找不到路了。

然后这里已经没有main函数了,直接用的_start,这个属于覆盖的方式,那么我们自己定义一个名字,该怎么处理呢?

然后使用参数 gcc -o hello hello.c -nostartfiles -efuck_main  ,-e这里就是 -enter的缩写,代表指定入口,通过这个操作,最终我们实现了没有main函数的一个程序,并且能够运行。

今天在这里分享一个比较有用的命令,在我们开发移植三方代码时候,会遇见很多未定义,包含错误,链接失败,这时候就需要定位我们的编译器参数,echo 'main(){}'|gcc -E -v - 这个可以看到详细的头文件,链接库的引用信息,当然我们可以使用--sysroot去指定,同时配合着 -I -l 参数。

到这里就完了吗?必然不是,我们看了如何修改入口函数,我们如果想要在main前后做一些动作呢?我们晓得的是动态库是有这个机制的,我们静态可执行库,也是有的,具体是:

这里运行结果:

我们可以清晰的看到,前后有了输出,那么我们看下这个最终的elf,这里找到after_main具体存放位置,而这个对应位置的方法,会在调用main之后进行遍历。所以这个是可以声明多个的。

而关于退出,还有个优雅的方式,就是int atexit(void (*)(void));,这个是一个设置退出方法,然后在main结束后,会进行执行,这里就是注册,很好理解。

为什么有main函数,主要是约定成俗,你让别人用你的东西,那必然要给他一个入口,也就是你的系统跟他关联的那个定义,main函数就是c语言开发,大家约定的入口。

但是在嵌入式开发当中,因为整个的系统,都是由我们处理,从启动,加载,运行,所以我们是可以不指定main函数,可以自己来约定。

好了第一讲就分享到这里,下一节我们来说下,c语言main函数的多种写法,其中一个标准的写法是带有:参数argv和argc,下一节说下这个是如何查找,定位的。

~~ end not end ~~


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466456.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

源码包安装

一、源码包和RPM包的区别 1、区别 安装之前的区别:概念上的区别 安装之后的区别:安装位置不同 2、RPM包安装位置 是安装在默认位置中 注:安装位置是写RPM包的作者决定的 注:RPM包支持指定安装位置,但是不建议指定位置安…

Linux下修改SSH登录端口

Linux下修改SSH登录端口LINUX 的默认SSH 端口是 22。为了防止别人暴力破解,建议修改SSH 访问端口:vim /etc/ssh/sshd_config 找到Port 22 这一行,这是是默认端口22,现在改成Port 1234这个数字自己定,但是不要超过65536…

五岁的时候,你在干什么?

文章写在2021.2.7号——想不到啊想不到,这么快你就五岁了。今天是楠哥的生日,在五年前的今天,小伙子在深圳宝安妇幼出生,刚出生的时候,样子很丑,第一次见面,我心情很紧张,不怎么敢靠…

TQ210——核心板和底板

TQ210——核心板和底板 1、TQ210简介【TQ210_COREB核心板 TQ210_BOARD_V4底板】 三星Cortex-A8 S5PV210芯片,运行最大频率1GHZ,处理器内部为64/32位总线结构,32/32KB一级缓存,512KB二级缓存。自带3D加速引擎(SGX540&a…

“华为天才少年”自制百大Up奖杯,网友:技术难度不高侮辱性极强

来源:雷锋网B站硬核黑科技Up主、AI算法工程师稚晖君,停更了好一阵子后,这位自称野生钢铁侠的超硬核Up主终于又发布了新作品。之所以停更这么久,Up主解释说,不是因为在野外被捕了,纯粹是因为工作太忙了。熟悉…

终极教程,带具体实验现象,1个GPIO控制2个LED显示4种状态,欢迎讨论!

芯片之家前几天发了一篇文章,讨论1个GPIO控制2个LED显示4种状态,并没有带具体的实验现象,有点小遗憾:绝妙!1个GPIO控制2个LED显示4种状态,什么?你不信?(点击阅读&#xf…

《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #15 ramzswap

HACK #15 ramzswap 本节介绍将一部分内存作为交换设备使用的ramzswap。ramzswap是将一部分内存空间作为交换设备使用的基于RAM的块设备。对要换出(swapout)的页面进行压缩后,不是写入磁盘,而是写入内存。可以使用的内存仅为完成压…

TQ210——底板部分原理图

TQ210——底板部分原理图 1、主电源接口(过压过流保护) 2、串行接口 2路5线RS232电平的DB9接口,4路TTLT电平扩展接口 COM1和PC之间通信需使用直连串口线 COM2和PC通信需使用交叉串口线 接口UART2可接GPRS模块实现打电话发短信功能&#xff1b…

有趣的灵魂百里挑一,Linux同学你低下头干嘛,起来说下这个问题。

今天我们不讲源码,不说面试题,我们来说点轻松的,聊点好玩的,我们来看看linux下有哪些酷酷的,有意思的命令。0x00 sl - 呜呜,让开,小火车来啦0x01 cowsay - 一起来 say hello0x02 cmatrix - 超级…

nodejs在cmd提示不是内部或外部命令解决方法

今天用cmd安装个库,结果发现node不是内部命令,于是搜索了下解决方法,解决方法是: . 找到变量值中node的安装地址,比如C:develop\nodejs,如果不是这个地址改成现在新的安装的地址,然后保存,重新打开cmd,输入 node -v 查看版本号,就会发现一切正常啦!当然这只针对于安…

用mtrace定位内存泄漏

一. 缘起有的公众号读者,看完我上次写给大学生的查bug方法后,希望我多分享一些查bug的实践经验和具体步骤,比如如何查内存泄漏和core dump问题。所以,就打算写这篇文章。二. 内存泄漏简介内存泄漏,是一个谈虎色变的问题…

为什么每个人都应该尝试Ubuntu下篇 Why Everyone Should Try Ubuntu 分享

但是老实说,我认为 Ubuntu 拥有长期的生存能力重要于其短期的实用主义。最近几年来,对于改进 Linux 桌面方面,Ubuntu 做得比其他发行版本要多。这就是我已详细讨论的,其带来的实际好处,但它也有许多不明确的地方。感谢…

陪我长大的村,镇,学校和家乡

我们村在广西河池市金城江区九圩镇江潭村山岳屯上面的字可以省略,因为看起来确实麻烦。地图上是这样显示的。小说我们村的那座桥,那座老桥据说是我爷爷那一辈人建起来的,用的是实打实的大石头。我上小学那段那会,我们同龄的小孩都…

Linux硬盘分区

MBR分区主分区:14,一块硬盘最多4个主分区,对主机必须有,主分区可以格式化ntfs,存数据。扩展分区:14,一块硬盘最多一个扩展分区,可以没有扩展分区,可以划分成更小的单元&a…

使用FileZilla Server轻松搭建个人FTP服务器

使用FileZilla Server轻松搭建个人FTP服务器 添加一个用户,然后在“共享文件夹”下设置将要设为FTP目录的文件夹和操作权限,点击确定 https://jingyan.baidu.com/article/ed15cb1bb6de421be3698188.html 可以为不同的用户创建不同的目录,新建…

TQ210——启动方式

TQ210——启动方式

AngularJS:应用

ylbtech-AngularJS:应用1.返回顶部 1、AngularJS 应用 现在是时候创建一个真正的 AngularJS 单页 Web 应用(single page web application,SPA)了。 AngularJS 应用实例 您已经学习了足够多关于 AngularJS 的知识,现在可…

你可能对电灯泡一无所知

今天在公众号“电路啊中看到一篇推文”超低成本的LED恒流驱动电路[1] ,作者讲述了看到一个仅仅售价1元人民币的LED灯泡,并包邮时所感到的惊讶。为了消除惊讶,作者还花巨资(1)购买 薅羊毛 了该款灯泡并拆开一看究竟。▲…

TQ210——S5PV210启动过程

TQ210——S5PV210启动过程 1、S5PV210内存地址映射 S5PV210 含有一个大小为64KB的IROM,起始地址为0xD0000000,结束地址为0xD000FFFF;含有一个大小为96KB的 IRAM,起始地址为0xD0020000,结束地址为0xD0037FFF;内存起始地…

composer-安装插件包

上一步完成后,选定国内镜像地址,以为下载插件包做准备 https://pkg.phpcomposer.com/ 安装完componser后使用下面这条命令即可(设置国内镜像地址): composer config -g repo.packagist composer https://packagist.phpcomposer.com 插件包地址…