复撸C系列开篇-Hello World

一直以来想写技术博客,但迟迟未行动,如今终于下定决定,还是来写一写,顺便巩固一下自己的知识。

废话不多说,就参照《C语言程序设计(第2版)》,从头过一遍吧。


1.Hello World

一开头,基本是每个程序员都熟悉的第一个程序:


#include <stdio.h>

int main()

{

printf("Hello world!\n");

return 0;

}


也许很多人会觉得:这没什么啊,不就一句向控制台打印一句Hello world 吗?但我想的是通过这个去了解更多的东西,因为很多人(包括我)在写了很久程序之后,才明白了什么叫“语言”,什么叫“库”,C语言本身是没有任何的“printf”给你用的。

那第一句 "#include <stdio.h>"  表明: 我要引入一个名叫 "stdio.h"这样的文件库,里面有一个叫"printf"的函数。

第二句"int main()"  表明: 这是程序的入口,为何要用"main"做入口?因为编译器就这么找的,游戏规则你得遵守,你要是高兴,完全可以自己写个编译器,规定一个名叫“fuck you”的函数入口。

第三句”printf("Hello world!\n")“, 表示调用了一个名叫printf的函数,传给它一个字符串指针,当然你得明白,这里是常量字符串指针。

那我们来研究下printf()是如何实现的。

在这句上打个断点,然后执行:


跟进去:



这尼玛是个鸟? 这么简单一句里面还这么复杂?

我们一个个的来看,可以看见”Hello world\n“传进来了。

”va_list“ 是个毛?  这玩意实际上就是个  char * 的指针,暂且不管其他两个 buffing 和 retval,来看下面有个宏 "va_start",找到它的定义:


我擦,这又是毛? 跟进去再看看


这个很明白,就是取个地址而已。


这个?尼玛跟天书一样,又是减又是位运算的,一开始我也不懂,后面网上搜了下别人的讲解才知道,这个是保证内存对齐的玩意,很高端,至今我还有点迷糊,不过不用过分纠结。反正就是计算它大小

我们回到刚才这句:



这句可以简单理解为: arglist = (va_list)(&format) + sizeof(format)        

取传进来字符串指针的地址,再加一个sizeof(char*) ? 这是搞鸡毛?我理解了很久,才初步推断这是函数调用时把参数压栈,然后这样那首参数地址加一下第一个参数的大小,自然也就得到了第二个参数的地址(也就是我们写: printf("This num is : %d",n) 这个n的地址), 不知这样理解对否? 还请高手指教。

那这意思明了了,就是arglist现在只想后面不定参数的第一个参数。

再往下,这句


再跟进去:


OK,了解了这是给stdout加个锁,至于什么是锁我想不用多说,了解点多线程的都知道的。

那传进来的stdout,我们再看看它到底是个什么鸟,虽然一直听,我想自己去研究的貌似还挺少。

跟过去:


再进__iob_fun(

)


 再跟:


噢,Bitch,终于找到你了,是个FILE的数组,这里_IOB_ENTRIES设了上限是20,可以看见有三个初始就有的大家经常听见的“stdin”,“stdout”,"stderr"。

找到FILE的定义:


就这么个玩意。说到这里我想说一下,有很多初学者认为这个语言屌,那个语言妙,其实说白了还不就是一些基本的东西组成的,再往下就是二进制了。所以与其纠结于XX语言好,XX语言妙,不如探究下本质,我也是因为想从本质上去发现语言,才有了写文的初衷。

扯回来,这里我们大概知道怎么回事了,printf一进来就把输出流锁住,然后进到这里来:


这里做一些初始的检查工作之类的,暂且不管。

主要看这一句:


撸进去:


我草?这是个毛,里面这么混乱,printf里面这么屌它妈妈知道吗?

暂且不要过于纠结这么多参数以及略长的函数以及复杂的循环,我们找找主要的,

到这里:


终于,这个传进来的"Hello World\n"开始起作用了,真麻烦啊。。。。

可以看见它在扫描 format这个字符串 ,也就是“Hello Wordl\n”,一直扫到末尾"\0"结束符。中间还有很多的杂七杂八的判断之类的,什么语言区啦,状态啦,然后麻痹的一长串恶心的switch case ,终于来到这句:


往里面写,也就是把当前扫描到的往 stdout这个buf里写,因为这里没有带什么“%s%d”之类的,所以处理过程还是相对比较简单。

噼里啪啦写完了之后:


返回 往里面写了多少个字符。OK,这个函数执行完了,临时的buffing里面已经有了内容。




最后_ftbuf 把buffing的内容填充到stdout里面去,至此,终于差不多完了。

之前我们锁了stdout,有锁当然就要解锁:


然后返回写入的字符 :

然后刚才调用的函数传的参数弹栈,也就是“Hello World\n”这个常量字符串指针变量弹出来,回到mian函数:


最后返回0,OK,至此我们的Hello World便完成了。


这里 只讲到了va_list  va_start 没有说 va_arg,因为初篇只有“Hello World\n”这么个简单的字符串,所以没有提及复杂的处理,后面会讲到。


初次写作,还请大家批评指正。


ps.转载的话(估计也没人转 ,有人看没有都是一回事╮(╯_╰)╭),还是注明个出处吧? 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值