Linux编译器——gcc/g++的使用
- 一、快速认识gcc/g++
- 二、程序的翻译过程
- 2.1 预处理(.i文件)
- 2.2 编译(.s文件)
- 2.3 汇编(.o文件)
- 2.4 链接(生成可执行文件或库文件)
- 三、认识函数库
- 3.1 静态库
- 3.2 动态库库
- 3.3 .dll(windows的动态库)缺失问题
- 3.4 动静态库总结
一、快速认识gcc/g++
编译生成可执行程序的方法:
可以形成一个指定名称的可执行程序有两种方法:
C语言源程序即可以用gcc编译也可以用g++编译,方法都是一样得。
C++源程序只能用**g++**编译器进行编译。(用gcc编译会报错)
二、程序的翻译过程
为什么c生万物?
早期语言是二进制,发展成汇编语言(划时代的东西,操作系统和编译器等诞生),丹尼斯里奇设计了更方便的语言(c语言),后来出现的面向对象语言c++,Python等编译器都是C语言写得,java的虚拟机是c++写得,所以c生万物。
先有语言还是先有编译器?
先有语言在有编译器,这个语言比编译器要出现的早一下(用二进制写得汇编编译器)。
如图:
语言的自举过程
总结:
c->低级语言写一个c编译器->能形成软件
c编译器->c->低级语言写一个c编译器->形成了用c写的编译器
c->用c写的编译器->编译c语言
c编译器优化v2->用c写的编译器v1->v2编译器
2.1 预处理(.i文件)
预处理功能 主要包括宏替换,头文件包含展开(所谓的头文件展开,本质是在预处理的时候,将头文件的内容拷贝至源文件),条件编译,去注释等。
预处理指令是以 # 号开头的代码行 。
#防止头文件被重复包含,为什么?
通过条件编译,将重复的编译进行去掉 。(命令行定义:gcc hello.c -o hello.exe -D VERSIONI=1)
gcc -E hello.c -o hello.i// 从现在开始进行程序的翻译过程,当预处理做完的时候,就停下来。
选项 “-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
选项“-o”是指目标文件(object)。
“.i”文件为已经过预处理的C原始程序。
2.2 编译(.s文件)
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。
gcc -S hello.i -o hello.s //从现在开始进行程序的翻译过程,当编译工作做完,就停下来。
“-S” 选项进行查看,该选项只进行编译而不进行汇编,只生成汇编代码,并生成.s 文件 。
2.3 汇编(.o文件)
汇编阶段是把编译阶段生成的 “.s”文件 转成 目标文件 “-o”
gcc -c hello.s -o hello.o //从现在开始进行程序的翻译过程,当汇编工作做完,就停下来。
选项 “-c” 可看到汇编代码已转化为 “.o”的二进制目标代码
此时的形成的Linux下的 .o 二进制文件相当于windows下的 .obj可重定位目标二进制文件,是不可执行程序,因为还差一步链接的过程。
2.4 链接(生成可执行文件或库文件)
在成功汇编之后,就进入了链接阶段 。自己编写的代码也被打包成.o文件,库文件也是被打包成.o文件,最后将他们这两个.o文件进行链接。
gcc hello.o -o hello //自己编写的代码被打包成.o文件,库文件也被打包成.o文件,最后将他们这两个.o文件进行链接。
三、认识函数库
我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?
答案是:系统把这些函数实现都被列到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。
查看Linux下的头文件:
ls /usr/include/
库的区分:
3.1 静态库
静态库是指编译链接时,把库文件的代码全部加入拷贝到可执行文件中 ,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名 一般为 “.a”。
3.2 动态库库
与静态库相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时,运行链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so” ,如前面所述的 libc.so.6 就是动态库 。
3.3 .dll(windows的动态库)缺失问题
被多个使用者共享使用,一旦缺失,所有程序都不可以运行了!!
.dll(windows的动态库)缺失的可能场景:
1.在链接的时候,病毒对你的代码进行了修改(病毒:对库进行恶意替换),当链接时对应的库文件.dll进行链接时,可执行程序就可以跑起来了,就可以对你的文件进行任意的修改了 。
2.杀毒扫描的是:系统之中可能隐藏的可执行程序 以及 各种静态库 。可能是在扫描过程中,扫描软件可能本身就存在各种bug,扫描的时候将你的库文件搞没了也是有可能的。
3.4 动静态库总结
1.函数库
函数库一般分为静态库和动态库两种。
动静态库本质就是文件,头文件也是文件 。
2.动静态库优缺点
动态库:(动态链接)
优比较节省资源,不会出现太多的重复代码----资源磁盘,内存,网络等资源。
缺点:对库的依赖性比较强----旦库丢失,所有使用这个库的程序都无法运行。
静态库:(静态链接)
优:不依赖库,同类型平台中都可以直接运行使用。
缺点:可执行程序体积比较大,比较浪费资源----资源磁盘,内存,网络等资源
3.生成动静态库的命令
gcc -o myfile myfile.c //生成动态的文件,动态链接1
gcc -o myfile-static myfile.c -static //生成静态的文件,静态链接2
注意:如果linux里没有安装c/c++静态库, 进行2号操作会报错,这时候我们就要安装c/c++静态库。
安装静态库命令:
yum install -y glibc-static libstdc++ -static
查看是否安装: