vc6下usb编程_从零开始,学习windows编程 - 从libc.lib开始!

10c208f7dfb6df4fb59d7de654fcffe3.png

从上一篇"从零开始"文章中,大家已经了解到有C运行时库这个概念,这个不算是新东西,但是一般都隐藏在幕后,C/C++语言教学的时候不讲,windows/linux编程的时候似乎也不会专门讲到。不过它一般是我们C/C++编程中默认会使用的一个重要部分。回想想,我们随手打出的strcpy, memset, memcpy等等,不就是C运行时库所提供出来的东西吗?

既然这样,就要好好研究一下这个东西了。

前面已经说过,针对单线程/多线程,静态/动态链接,是否是debug版本,VC6的C运行时库提供了6个版本。具体可以看下面的截图。

8d9d9a73c80d3152f43d0c454d4ae168.png

而其中每一个选择对应的LIB文件。这里也不全部一下子将所有的都研究一下,还是按照由浅入深的原则,从最简单的部分开始,当然,也会在牵涉到其他部分的时候,进行一定的说明。

最简单的当然是Single-Threaded,同时也是static link的了。其对应的文件为LIBC.LIB。对应CL的编译选项为/ML。既然要研究这个LIB文件,那当然是有源码最好了,jjhou不是说过,“源码面前,了无秘密”吗。那我们在哪里找到有源码呢?

————————————

只要你安装了VC6,它就带有CRT的源码,具体目录和你安装VC6的目录有关,在我电脑上的路径为“d:Program FilesMicrosoft Visual StudioVC98CRTSRC”,你进去之后会发现,里面有不少熟悉的名字,如“MATH.H”、“STDIO.H”、“STDLIB.H”、“STRING.H”等,由于C运行时库被C++运行时库包含,所以这里面还有C++标准库的代码,所以还能看到“IOSTREAM”、“CSTDIO”、“algorithm”等C++的std头文件。

————————————

这里就出现了一个问题,这里的文件有成百上千个,我们一个个全部看是不可能的,那如何找出关键的部分来呢?

如果还对上一篇的分析有印象,并且带有问题的同学,应该很容易联想到,我们在link不带有defaultlibs信息的hello.obj文件时,出现了两个LINK2001错误,分别是找不到_printf和_mainCRTStartup这两个symbol文件。

编译器CL在编译C程序的时候,内部将需要编译的函数前面加上下划线(_)用来标识,_printf具体指的就是printf函数,_mainCRTStartup则是mainCRTStartup,是在哪里使用的呢?

我们已经知道,printf函数和mainCRTStartup函数的实现都是在LIBC.LIB中,printf,是我们main函数中用来打印信息的,而mainCRTStartup,则是hello.exe的入口(entry point)。

入口

学过C语言的人都知道,有一个main函数,是一个程序的入口。不管怎样,main函数是特殊的。

使用汇编的童鞋都知道,汇编的入口函数只是一个符号,是可以随意定义的,之后就从入口开始,PC一条条的开始执行汇编代码。对于C程序来说,main也是一个符号而已,不过这个符号与汇编的_start有些区别,_start可以用其他符号直接代替,而在windows系统下,VC开发的环境中,我们的hello.exe的main函数之前还有一个mainCRTStartup(呼,好多限制条件,好绕口……)。

crt0.c

为什么需要mainCRTStartup呢,我们还是要看一下源码实现。先搜索到mainCRTStartup所在的文件,为crt0.c,其全部代码有400多行因篇幅原因就不写出来了,想要深入了解的小伙伴可以找我。

用到的宏

可以看到,里面使用了很多的宏,同时还涉及到一些例如wWinMainCRTStartup,WinMainCRTStartup,wmainCRTStartup以及我们现在需要查看的mainCRTStartup。根据不同的宏来选用不同的代码实现。

_WIN32

CRTDLL

WPRFLAG

_WINMAIN_

_MT

_M_MPPC

2b9cd98a0aeb6e752156f0fac86aa914.png

整理之后的代码

因为我们这里分析的是mainCRTStartup,用的是命令行程序,非unicode版本,单线程,非PPC。所以可以将对应的一些宏去掉,最终整理得到的代码(不包含辅助函数)为:

849d8e619524999a81d92684a89963b8.png

2e87da7cf27dd4c513eb0dc57db59be0.png

e73b630e6dc51f98963599a04ba2c837.png

这样,就可以分析一下得到的代码了。同时,从代码中可以看到微软的编码风格,学习到一部分。

在mainCRTStartup()函数中,主要调用了GetVersion, _heap_init, fast_error_exit, _ioinit, GetCommandLineA, __crtGetEnvironmentStringsA,_setargv, _setenvp, _cinit, exit,以及最重要的main函数。

其中fast_error_exit位于crt0.c中,实现如下

b6393db66533a338d7cf6848057e58a2.png

其他一些函数所在的文件或者说明如下,感兴趣的同学可以自行研究,这里因为篇幅原因,就不一一展开了。

7586e2ce271159d148830b2ca72bfab5.png

由此可见,mainCRTStartup为main函数做了一些初始化的工作,包括创建heap,初始化low IO,以及命令行参数和环境变量的获取,和初始化C runtime Data。

▓当没有做这些初始化工作,而直接使用main作为入口函数的话,是会出现很多问题的,具体在下一篇写吧。

▓由于涉及到的这部分,网络上面的参考较少,自己揣摩出来居多,有错误难免,希望大家批评指正。

我是一名从事了10年开发在退休边缘垂死挣扎的高龄程序员,最近我花了一些时间整理了一个完整的学习C语言、C++的路线,项目源码和工具。对于想学习C/C++的小伙伴而言,学习的氛围和志同道合的伙伴很重要,笔者推荐一个C语言/C++编程爱好者的聚集地>>>C/C++编程项目开发学习,素材笔记,项目源码等,还有新鲜出炉的学生成绩管理系统等!

欢迎初学和进阶中的小伙伴。希望你也能凭自己的努力,成为下一个优秀的程序员。工作需要、感兴趣、为了入行、转行需要学习C/C++的伙伴可以一起学习!”

关注我,带你遨游代码世界!

下面这些是C/C++能做的 :

服务器开发工程师、人工智能、云计算工程师、信息安全(白客)、大数据 、数据平台、嵌入式工程师、流媒体服务器、数据控解、图像处理、音频视频开发工程师、游戏服务器、分布式系统、游戏辅助等!

最后分享一张C/C++编程学习路线图给爱学习的小伙伴们

2c895d5938a6c016d41af4e593484285.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值