【Linux】系列文章目录
【Linux】基础常见指令:http://t.csdn.cn/hwLPb
【Linux】基本权限:http://t.csdn.cn/faFZg
【Linux】软件包管理器yum与环境开发工具vim:http://t.csdn.cn/LEqkm
目录
【Linux】系列文章目录
前言
一、gcc选项总览
二、gcc如何完成?
1.预处理 ( 进行宏替换)
预处理结果展示:
2、编译(生成汇编)
编译结果展示:
.iso镜像文件
3、汇编(生成机器可识别代码)
4、连接(生成可执行文件或库文件)
三、函数库
1.静态库
2.动态库
最后
前言
gcc/g++是一个编译器(gcc专门编译C语言;g++专门编译C++,也可以编译C语言)。
本文将从程序的翻译,包括预处理、编译、汇编、连接四个步骤,主要对gcc以及函数库分别展开讲解。
提示:以下是本篇文章正文内容,下面案例可供参考
一、gcc选项总览
选项 功能 -E 只激活预处理,这个不生成文件,故需要把它重定向到一个输出文件里面 -S 编译到汇编语言不进行汇编和链接 -c 编译到目标代码 -o 文件输出到 文件 -static 此选项对生成的文件采用静态链接 -g 生成调试信息(GNU 调试器可利用该信息) -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库 -o0 表示没有优化 -o1 为缺省值 -o2 -o3 优化级别最高 -w 不生成任何警告信息 -Wall 生成所有警告信息 注:-O0、-O1、-O2、-O3 为编译器优化选项的4个级别。
在后文gcc如何完成部分将会对gcc选项有更近一步的解释。
二、gcc如何完成?
1.预处理 ( 进行宏替换)
对源程序进行头文件展开,条件编译,进行宏替换,去注释等。
对.c文件进行预处理使用gcc -E命令,表示从现在开始进行程序的翻译,预处理做完,就停下来,形成.i文件,.i文件中存放预处理后的结果
gcc -E myfile.c -o myfile.i
在vim中输入vs myfile.i 然后回车就能查看.i文件内容
vs myfile.i
预处理结果展示:
2、编译(生成汇编)
把文本文件翻译成二进制文件,形成汇编语言
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
对文件进行编译使用gcc -S命令,表示从现在开始进行程序的翻译,当编译做完,就停下来。形成.s文件,.s文件中存放编译后的结果
gcc -S myfile.i -o myfile.s
编译结果展示:
.iso镜像文件
3、汇编(生成机器可识别代码)
汇编->可重定位目标二进制文件,不可以被执行的,bin.obj
----只把我们自己的代码进行翻译形成二进制目标文件
汇编阶段是把编译阶段生成的“.s”文件转成目标文件。读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。
对文件进行编译使用gcc -c命令,表示从现在开始进行程序的翻译,当汇编做完,就停下来 ,形成.o文件,.o文件中存放汇编后的结果
gcc -c myfile.s -o myfile.o
请观察以上命令及形成的结果文件。
4、连接(生成可执行文件或库文件)
将我们自己形成的.obj文件和库文件进行某种合并,将程序与相对应的库链接起来,形成可执行程序。
gcc命令 或gcc -o 命令
gcc [文件名]:将源程序进行编译,形成a.out文件,如果想要生产我们自己需要的文件名,使用gcc -o命令。
-o 后面紧跟指定的形成可执行文件的名称
gcc -o myfile myfile.c gcc myfile.c -o myfle //两行代码效果一样 ./a.out // ./+文件名 是指执行该文件
在成功编译之后,就进入了链接阶段。
接下来请思考一个问题:
我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?
答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函 数“printf”了,而这也就是链接的作用。
(能在Linux下进行C、C++代码的编写和编译,是因为Linux系统默认已经携带了语言级别的头文件和语言对应的库!)
在这里涉及到一个重要的概念------函数库。
三、函数库
函数库一般分为静态库(专门让编译器对用户的程序进行静态链接的)和动态库(专门让编译器对用户的程序进行动态链接的)两种,库的本质也是文件。Linux默认使用的是动态连接和动态库。
1.静态库
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。后缀名一般为“.a”
- 静态链接:将我们所需要的库中的代码拷贝到我们的程序中。
- 静态链接一旦形成就不再依赖任何库,自己就可以独立运行。
- 因为自身拷贝问题,比较浪费空间。
一般的云服务器,默认都是只有动态库。如果在静态链接的时候,链接可能会报错,因此需要安装静态库,代码如下。
yum install glibc-static libstdc++-static -y
安装示例:
2.动态库
(动态库==共享库)
与静态库相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如 gcc myfile.c –o myfile。
- 动态链接:将你所需要的库中的代码地址拷贝到你自己的可执行程序中相关的位置。
- 动态链接形成还是依赖动态库,一旦动态库缺失,程序便无法运行。
- 因为可以做到被大家共享方法,所以真正的实现永远都是在库中,程序内部只有地址,比较节省空间。
ldd myfile // ldd+文件名 能够查到该程序所依赖的库
gcc默认生成的二进制程序,是动态链接的,这点可以通过 gcc选项 file 命令验证。
file myfile
注意:头文件!=库文件
- 在C语言中,头文件提供对常量的定义和对系统函数及库函数调用的声明(函数原型)。存放的标准位置是/usr/include目录及其子目录。
- 库文件是一组预先编译好的函数的集合,可以说是头文件函数原型的实现。存放的标准位置是/lib和/usr/lib目录。库文件总是以lib开头。标准C语言库文件(函数库)为libc.a文件。
最后
快乐的时光总是短暂的,以上就是今天要讲的内容,本文详细介绍了小赵同学对Linux编译器-gcc/g++以及函数库的初步认知以及用例。欢迎家人们批评指正。小赵同志继续更新,不断学习的动力是宝子们一键三连的支持呀~