【Linux】Linux环境基础开发工具使用(三)gcc/g++ 编译器【 Linux编译器-gcc/g++编译器的使用 选项以及介绍 、gcc编译过程的详细讲解 、函数库,动静态库的理解】




Linux编译器 — gcc/g++ 编译器的使用

一、背景知识

  1. 预处理(进行宏替换)
  2. 编译生成 汇编)
  3. 汇编生成 机器可识别代码
  4. 连接生成可执行文件或库文件)


二、gcc如何完成:gcc/g++ [选项] 要编译的文件 [选项] [目标文件]


格式 gcc/g++ [选项] 要编译的文件 [选项] [目标文件]

gcc与g++一样,都能进行编译,选项都一样
C语言 — gcc(推荐)/g++ ; C++语言 — g++



语言的进化与产生 [ 语言与编译器 自举 的过程 ]

  • 使用二进制的这种编程方式,效率太低了。
  • 于是就改进了二进制的编程方式,产生了汇编语言 — 不能在计算机上直接执行的 =》编译器 =》就有了操作系统【大名鼎鼎的Unix第一版就是用汇编语言写的】
  • 汇编语言用起来还是不太好使 =》C语言 诞生了
  • C语言用久了,发现面向对象用的比较多 =》(面向对象编程)C++,(解释型/半解释型语言)【 解释器都是由C语言写的 】Python,shell,Java【Java的虚拟机都是用C语言写的】【C生万物】


在这里插入图片描述

用底层语言 写上层语言的编译器 =》
(形成软件)即可将上层语言进行编译 =》
再用上层语言通过 用底层语言写的编译器(可对上层语言进行编译),编译出 用上层语言写的编译器=》
就有了 用上层语言写的 上层语言编译器:这个过程叫作 语言与编译器的自举

汇编语言 转二进制,这些已经由前人写好了。所以只需把 C编译成汇编语言 即可。【 所以 分阶段的 才有了下面 编译过程中的多过程



如下指令中,与 -o(object 目标文件)紧邻的形成的指定的可执行程序(要编译的文件)剩下的都可以叫 源文件
-D 指定的宏,
不同版本,是功能上的问题 =》免费版的少,专业版的功能更丰富,且他们重叠的内容都是一样的
那是 放在一起维护,还是分开维护 =》答案当然是维护一份代码好

=》通过 条件编译,对代码进行动态裁剪,软件的多版本的维护。



(1)预处理(进行宏替换) .i文件为已经过预处理的C原始程序

预处理功能 主要包括 宏定义,文件包含,条件编译,去注释等。

预处理指令# 号开头的代码行
# 防止头文件被重复包含,为什么?
通过 条件编译,来 将重复的编译进行 去掉

在这里插入图片描述


//实例y
gcc –E hello.c –o hello.i //  .i文件为 **已经过预处理的C原始程序**。

[ 选项 ]

  • 选项 “-E”,该选项的作用是gcc 在预处理结束后 停止编译过程(End)。【从现在开始进行程序的翻译过程,当预处理做完的时候,就停下来】

选项“-o”是指 目标文件object),【 不想写后缀,编译器是会自动形成与源文件同名的后缀 】
“.i”文件为已经过预处理的C原始程序

如上指令中,-o(object 目标文件)紧邻的形成的指定的可执行程序(要编译的文件)剩下的都可以叫 源文件



(2)编译(生成汇编).s文件

在这个阶段中,gcc 首先检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,
检查无误后,gcc 把 代码 翻译成 汇编语言


[ 选项 ]

  • 用户可以使用 “-S” 选项来进行 查看,该选项 只进行编译而不进行汇编生成汇编代码,生成对应的 code.s 文件【 从现在开始进行程序的翻译(生成汇编代码),当编译工作做完,就停下来 】
//实例
             // 与 -o 紧邻的是 形成的指定的可执行程序   //剩下的都可以叫源文件
 gcc –S hello.i –o hello.s //汇编代码


(3)汇编(生成机器可识别代码)目标文件 “-o”

汇编阶段 是把 编译阶段生成的 “.s”文件 转成 目标文件 “-o”
读者在此可使用

[ 选项 ]

  • 选项 “-c” 就 可看到 汇编代码 已转化为 “.o”的二进制目标代码
//实例:
gcc –c hello.s –o hello.o

此时的 形成的Linux下的 .o 二进制文件 相当于 windows下的 .obj可重定位目标二进制文件是不可执行程序因为还差一步 链接的过程
在这里插入图片描述



(4)连接(生成可执行文件或库文件)

在成功编译之后,就进入了 链接阶段 。自己编写的代码也被打包成 .o文件,库文件也是被打包成 .o文件,最后将他们这两个.o文件 进行链接。

//实例
gcc hello.o –o hello


三、gcc 编译过程 总结

在这里插入图片描述



四、函数库

在这里涉及到一个重要的概念:函数库

我们的C程序中,并没有定义“printf”的函数实现。
在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现

那么,是在哪里实现 “printf”函数 的呢?

最后的答案是:系统把这些函数实现都被做到名为 libc.so.6库文件中去了。

  • 在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去C语言有自己的标准库,默认给你链接到上面去了 ,这样就能实现函数“printf”了,而这也就是链接的作用

  • 即使.o文件中的可执行程序什么都没有,也要跟C标准库进行链接。因为 Linux默认已经给我们提供了C语言的头文件了。

    libr64目录 下也 已经把很多的库都安装好了
    平台要支持开发,就必须要提前在系统中安装 语言的标准头文件+库文件(安装环境很重要的一步) 】
    在这里插入图片描述


ldd 即可 查到可执行文件它所依赖的库文件

在这里插入图片描述


无论是动态库还是静态库,你所依赖的库名称:将lib去掉,还有 .so.所带的后缀全部去掉
在这里插入图片描述


五、链接 — 动静态库的理解

函数库一般分为静态库和动态库两种。
动静态库 本质就是文件头文件也是文件
在这里插入图片描述

(1)静态库 .a

静态库是指 编译链接时把库文件的代码全部加入拷贝到可执行文件中 ,因此生成的文件比较大,但在运行时也就不再需要库文件了

后缀名 一般为 “.a”

(2)动态库 .so

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销

动态库一般后缀名“.so”如前面所述的 libc.so.6 就是动态库

gcc 在编译时 默认使用动态库完成了链接之后,gcc 就可以生成可执行文件,如下所示。

 gcc hello.o –o hello

gcc默认生成的二进制程序,是 动态链接 的,这点可以通过 file 命令验证。

> 动静态库 链接的理解

在这里插入图片描述



六、动静态库 小结

(1)函数库

函数库一般分为静态库和动态库两种。
动静态库 本质就是文件头文件也是文件
在这里插入图片描述

(2)动静态库优缺点

在这里插入图片描述

(3)动静态库 链接的理解

在这里插入图片描述



六、.dll(windows的动态库)缺失 问题

在这里插入图片描述
被多个使用者共享使用,一旦缺失,所有程序都不可以运行了!!

  • .dll(windows的动态库)缺失的可能场景:
  1. 在链接的时候,病毒对你的代码进行了修改(病毒:对库进行恶意替换),当链接时对应的库文件.dll进行链接时,则可执行程序就可以跑起来了,就可以对你的文件进行任意的修改了 。

  2. 杀毒扫描的是:系统之中可能隐藏的可执行程序 以及 各种静态库 。可能是在扫描过程中,扫描软件可能本身就存在各种bug,扫描的时候将你的库文件搞没了也是有可能的。



七、gcc选项

-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言不进行汇编和链接
-c 编译到目标代码

-o 文件输出到 文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息。GNU 调试器可利用该信息。
-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
-O0
-O1
-O2
-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-w 不生成任何警告信息。
-Wall 生成所有警告信息。

八、gcc选项记忆

ESc,-iso例子

猜你喜欢

转载自blog.csdn.net/NiNi_suanfa/article/details/134560392