目录
1.背景知识
程序翻译的过程是要经过4个阶段 且 每个阶段都有各自的任务:
1.预处理:去注释,宏替换,头文件展开,条件编译等,此时依旧是C程序
2.编译:C->汇编
3.汇编:汇编->可重定向二进制目标文件
4.链接:连接多个.o和.obj文件,合并形成一个可执行的.exe的文件(可执行程序)
而gcc只能用来编译C,g++可以编译C也可以编译C++。
2.gcc/g++安装
安装gcc、g++编译器以及内核文件:
yum -y install gcc gcc-c++ kernel-devel
补充:gcc -v 查看gcc版本;g++ -v查看g++版本。
3.gcc的使用
格式:gcc [选项] 要编译的文件 [选项] [目标文件]
3.1 直接形成可执行文件
gcc 文件名.c //可以把文件直接变为可执行程序
在Linux的命令行中,直接输入 ./可执行文件 ,就可以运行这个可执行程序。
3.2 预处理
gcc –E 文件名.c –o 文件名.i
- 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
- 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序。
- 预处理的主要功能包括去注释,宏替换,头文件展开,条件编译等,此时依旧是C程序。
3.3 编译
gcc –S 文件名.i –o 文件名.s
- 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
- 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查 无误后,gcc 把代码翻译成汇编语言。
3.4 汇编
gcc –c 文件名.s –o 文件名.o
- 在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。
- 汇编阶段是把编译阶段生成的“.s”文件转成目标文件。
- 汇编是生成机器可以识别的代码。
3.5 链接
gcc 文件名.o –o 文件名
- 经过链接就形成了一个test的可执行文件,这个可执行文件可以直接运行了。
那链接到底做了什么呢?
把 目标文件 和 库文件等文件给链接起来这就叫做链接。
1.要知道在一个程序当中,像printf这样的函数我们并没有去实现可是为什么我们却可以直接去使用呢?
是因为在链接的时候是把目标文件和它运行需要的函数库文件链接在了一起,此时就是形成了一个可执行程序,而像printf这样的函数它的定义就包含在库文件当中。
2.函数库是什么呢?
函数库就是一些函数的集合,每个函数都具有独立的功能且能被外界调用。我们在编写代码时,有些功能根本不需要自己实现,直接调用函数库中的函数即可。函数库又可以分为动态库和静态库,而对于动态库和静态库之间的区别就是编译链接的方式是不同的,动态库就是通过动态链接的库,静态库就是通过静态链接的库。
3.目标文件是怎么和函数库相关联起来的呢?
通过动态链接把目标文件和动态库链接起来,通过静态链接把目标文件和静态库链接起来,动态链接和动态库 与 静态链接和静态库这2种组合实际对应了2种方式,2种把库内容与目标文件关联起来的方式。
静态库:是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
动态库:与静态库相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。
动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件。
动态链接:
所谓的动态链接就是把动态库的地址拷贝到你的可执行程序当中去,然后通过这个地址去找到这个动态库,在这个动态库中去寻找相应的函数的实现然后返回给这个程序(此时库和这个程序是不在一个地方),所以动态链接是以这样的方式把动态库和目标文件关联起来的。
静态链接:
静态链接就是把这个可执行程序当中要用到的函数的实现给拷贝到自己的程序当中对应的位置处(编译时将库文件的代码嵌入到可执行文件中,形成一个独立的二进制文件),此时当自己的程序要去调用这个函数的实现时就可以不用由地址跑到库当中去寻找相关的实现了,而是跑到自己的程序中的一块空间当中去寻找关于这些函数的实现。
gcc选项归纳:
- -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面。
- -S 编译到汇编语言不进行汇编和链接。
- -c 编译到目标代码。
- -o 文件输出到 文件。
- -static 此选项对生成的文件采用静态链接。
- -g 生成调试信息。GNU 调试器可利用该信息。