首先了解一下---程序的编译过程:(ESc - iso)
1.预处理:宏替换 \ 展开头文件 \ 去注释 \ 条件编译,生成.i文件
2.编译,检查语法错误,生成 .s文件
3.汇编:将编译后的汇编文件翻译成二进制目标文件,生成.o文件
4.链接:生成可执行文件a.out
1.详解预处理阶段:
-E 将gcc过程停止到预处理阶段,-o指明生成的临时文件(test.i)
(1)条件编译
(2)头文件最大的意义:
---写代码
---支持代码的自动补齐
2.详解编译阶段:
预处理之后,生成的test.i文件仍旧是C语言,机器不能识别,在编译的这步要将它转为汇编语言。
-S 将gcc过程停止到编译结束阶段,-o指明生成的临时文件(test.s)
(1)汇编语言能直接执行吗?
二进制语言(纸带)-->汇编语言(有很多助记符...);汇编语言不能被直接执行。
3.详解汇编阶段:
汇编阶段生成的二进制目标文件也不是能直接执行的!!!
-c 将生成的汇编文件test.s经过汇编翻译成二进制目标文件,-o指明生成的临时文件(test.o)
4.详解链接阶段:
前三部分只是在翻译处理你写的当前代码!!!第四步链接是将你写的代码和c标准库中的代码合起来call,代码才能成功运行。形成可执行文件,可形成的二进制程序(库+你的代码)。
gcc 将生成的二进制目标文件test.o链接生成可执行文件,-o指明生成的临时文件存到(mytest)
(1)动态链接和静态链接
C标准库,是别人已经准备好可供直接使用的。我们所有使用库中函数的代码(eg.printf()),其中我们自己只写了该函数的调用,没有对应的实现!只有当链接的时候,对应的实现,才和我们的代码关联起来;链接的本质:无非就是我们要调用库函数的时候如何和标准库关联。
动态链接:和库建立链接<-> 库函数跳转。无论库出现什么问题,都会影响到本地的程序调用,但是形成的可执行文件小---节省资源(内存、磁盘、网络)。
静态链接:将我程序内部要使用的库中的方法拷贝一份,就完成了静态链接。不受库升级或者被删除的影响,但是形成的可执行程序的体积过大,形成了比较多的冗余代码。
(2)在Linux下库的命名:
动态库:libXXXXXXX.so
静态库:libXXXXXXX.a 去掉前缀和后缀后剩余的就是库的名称。
Linux下默认形成的可执行程序中,默认使用的是动态库 libc.so.6---c标准库
在Windows下原理是一样的;动态库:.dil;静态库:.lib;也同样是动态链接。
静态链接,拷贝的是.so内部的代码吗?不是,系统中必须存在.a结尾的静态库;/lib64/libc.a(静态库);一般而言,系统会自动携带静态库,如果不存在,需要自己安装。
如果系统没有携带静态库,用指令 sudo yum install -y libstdc++-static安装C++的静态库;使用指令sudo yum install -y glibc-static安装C++的静态库。
(3)系统本身,为了支持我们编程,给提供了什么?
提供 标准库.h---告诉我们怎么用(所有函数接口/参数/返回值...);标准的动静态库.so/.a---提供给我们方法。我们的程序通过使用头文件来链接动/静态库来形成可执行程序。