目录
一、预编译指令
1.1预处理功能
1.2指令
1.3问题扩展
二、编译(生成汇编)
三、汇编(生成二进制机器语言)
四、链接(生成可执行文件或库文件)
4.1库文件
4.2目标文件和库的链接
4.3动态库和静态库的优缺点
五、debug和release
一、预编译指令
1.1预处理功能
- 去掉注释
- 头文件的展开
- 条件编译
- 宏替换
1.2指令
- 预处理指令是以#号开头的代码行
- gcc下使用:gcc -E code.c -o code.i 来生成可执行文件
- 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程
- 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序
实例:
1.3问题扩展
-
为什么能在Linux下进行C/C++或者其他形式的开发呢?
-
C/C++开发环境不只是指gcc、g++、vs等编译器,更重要的是语言本身的头文件和库文件
-
在进行开发前,系统中一定要提前安装或者后续安装上C/C++相应的头文件和库
-
对于编译型语言,在选择对应的开发包进行下载时,必定也在同步下载头文件和库文件
-
使用ls /usr/include 可以查看Linux下包含的所以头文件
- 条件编译的应用场景
- 根据编译条件,裁剪掉某些社区版编译器所不需要的功能
- 经过预处理的源文件也是c语言
二、编译(生成汇编)
-
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言
-
用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码
实例:gcc -S code.i -o code.s
三、汇编(生成二进制机器语言)
- 汇编阶段是把编译阶段生成的“.s”文件转成目标文件(可重定向二进制目标文件,.obj)
- 可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码
- 生成的目标文件虽然是二进制,但是不能独立运行,要和库进行链接形成可执行文件才能执行
实例:gcc -c code.s -o code.o
四、链接(生成可执行文件或库文件)
4.1库文件
我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?
答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到 系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用
- 库文件实际上是.c(源文件)经过一定的翻译打包后形成的一个文件——可以达到只需要提供一个文件不需要提供多个源文件,隐藏源文件的功能
- 软件=头文件中方法的声明+库文件中方法的实现+代码
- Windows下存在以.dll为后缀的动态库和以.lib为后缀的静态库
- Linux下存在以.so为后缀的动态库和以.a为后缀的静态库
- 如何查看Linux的动态库和静态库?
ls /usr/lib64/libc.so*
ls /usr/lib64/libc.a*
4.2目标文件和库的链接
-
动态链接
动态库在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时跳转到库中去执行相应的方法,执行结束后再回到代码调用处继续往下执行,这样可以节省系统的开销。动态库不能缺失,一旦缺失,所有依赖于动态库程序都无法正常运行。
动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件。
- 静态链接
静态库是指编译链接时,把库文件的代码全部拷贝加入到可执行文件中,因此生成的文件比较大,但再运行时,该目标问津不会再依赖库文件了。
4.3动态库和静态库的优缺点
- 动态库:动态库为共享库,可以节约资源(磁盘空间,内存空间,网络空间);但动态库一旦缺失,所有依赖于该动态库的程序都无法正常运行
- 静态库:程序不依赖库,静态库销毁,后续程序可以正常运行;体积大,不可以节约资源
- Linux下,生成可执行文件时的默认为动态链接--需要提供动态库
- Linux下,要按照静态链接的方式,在进行编译时要添加选项-static
实例:gcc code.c -o code.test
gcc code.c -o code.test_static -static
可以看出,按照静态链接的方式形成的可执行文件比动态链接形成的可执行文件大
- 如果没有静态库,不能进行-static动态链接
- 如果没有动态库,只有静态库,而且gcc能找到该静态库,那么可以进行静态链接
- Linux默认优先动态链接,-static的本质:改变静态链接的优先级,只适配一次
- 不一定所有的链接都是动态链接或静态链接,也有可能时动态链接和静态链接混合的
五、debug和release
-
Linux默认生成的release版本
-
debug版本的可执行文件会比release版本的略大
-
要生成debug版本的可执行文件,可以在编译时添加-g选项
实例:gcc code.c -o code.test_debug -g
gcc code.c -o code.test_debug_static -g -static
- 生成的可执行文件并不是无序的二进制格式,而是有自己的格式--ELF格式
- file指令
实例:file code.test
file code.test_static