一:背景知识
1.预处理(头文件展开、去注释、宏替换、条件编译)
2.编译(由C生成汇编)
3.汇编(生成及其可识别代码)
4.连接(生成可执行文件或库文件)
二:gcc实现过程
1.预处理
预处理对应的指令为:
gcc -E test.c -o test.i
-E表示从现在开始,进行程序的翻译,等预处理做完就停下来,不在继续。
-o 要形成的目标文件。
test.i 表示(预处理的结果)显示在该文件中。
预处理主要进行的工作为:头文件展开、去注释、宏替换、条件编译。
我们以下述代码,对前三个进行测试:
经过预处理之后,如下图所示:
接下来,我们对条件编译进行测试,测试示例及其结果如下:
由上述图可知:通过条件编译,可以实现对代码的动态裁剪。
2.编译
编译对应的指令为:
gcc -S test.i -o test.s
-S 从现在开始,进行程序的翻译,等编译工作做完,就停下来。
test.s 显示在该文件中。
3.汇编
汇编对应的指令为:
gcc -c test.s -o test.o
-c 可以将汇编代码转为“.o”的二进制目标代码
打开test.o文件:
在此处 文件显示乱码,原因是 test.o 已经是一个二进制的文件了。
但是我们有一个指令可以用于查看二进制文件:
od test.o
但是我们打开之后,也还是看不懂。
4.连接
连接对应的指令为:
gcc test.o -o mybin
连接形成了可执行程序。
运行mybin
./mybin
5.函数库
在我们的程序中,我们并没有定义 printf 函数,并且在预编译包含的 "stdio.h" 也只有该函数的声明,而没有定义实现,那么是在哪里实现的 printf 函数呢???
我们的代码 + 头文件 + 库 = 我们的可执行程序头文件和库文件都是文件!所以所谓的开发环境安装一定要做什么工作???怎末理解???安装下载并拷贝头文件和库文件到开发环境的特定路径下,一定要能被编译器自己找到。
函数库一般分为静态库和动态库(居多)两种。
动态库一般后缀名为“.so”,静态库后缀名一般为“.a”
6.动态库 vs 静态库
动态库(共享库):是C/C++或者其他第三方提供的所有方法的集合,被所有程序,以链接的方式,关联起来。
静态库:是C/C++或者其他第三方提供的所有方法的集合,被所有程序以拷贝的方式,将需要的代码拷贝到自己的可执行程序中。
动态链接:库中所有的函数,都有入口地址,所谓的动态链接,其实就是把要连接的库中的函数地址拷贝到我们的可执行程序的特定位置。
静态链接:等价于将电脑搬回宿舍,随时都可以用,不需要去网吧。
动态链接的优缺点
优点:形成的可执行程序体积比较小,节省资源
缺点:一旦缺失,会影响使用该动态库的所有程序
静态链接的优缺点
优点:无视库,可以独立运行
缺点:体积太大,浪费资源
gcc 默认动态链接
如果我们需要安装 C/C++ 的静态库,可以使用以下命令:
安装成功如下: