【Linux】编译器gcc/g++ 、程序翻译过程、动静态库

参考文章:编译器-gcc/g++与调试器-gdb的使用

1.gcc/g++ Linux编译器

1.1. gcc与g++的安装

g++与gcc的安装指令:

sudo提权/root 的权限下,才能进行安装

 yum install gcc
 yum install g++

1.2. gcc与g++用法

两者用法基本一致

1.2.1.gcc用法

注意:gcc只能编译C语言

(1)执行后会默认在该目录下形成一个 a.out 的文件

gcc + 文件名      

(2)-o 后面+生成指定文件
-o 的位置随意,但是后面必须是新的指定文件

gcc -o 可执行文件a .c文件     //编译该.c文件,生成一个名为a的可执行文件
gcc .c文件 -o 文件名M      //编译该.c文件,生成一个名为a的可执行文件

1.2.2. g++用法

注意:g++既可以编译C++,也可以编译C语言

(1)执行后会默认在该目录下形成一个 a.out 的文件

g++ + 文件名      

(2)-o 后面+生成指定文件
-o 的位置随意,但是后面必须是新的指定文件

g++ -o  A .cpp文件     //编译该.cpp文件,生成一个名为A的可执行文件
g++ .cpp文件 -o A  //编译该.cpp文件,生成一个名为A的可执行文件

1.3. 程序翻译的过程

1.3.1. 前提知识:

语言的发展:二进制语言 ->汇编语言 - >C语言 - >C++,java,python

问题:

先有语言还是先有该语言对应的编译器呢?例如,先有汇编语言呢,还是先有用汇编语言写的编译器呢? 先有该语言。

假设现在有汇编语言,那么二进制语言、以及对应的二进制编译器(该编译器可以把汇编语言,翻译成二进制语言),都已经存在了。

因为编译器本身就是个软件,因此利用二进制编译器,来编写汇编语言组成的新编译器。

然后使用新的编译器(汇编语言编译器),去编译和完善自身的代码。

同样,第一个把c语言编译器,肯定是利用汇编语言所写能够让C语言变为汇编语言的编译器。这是语言和编译器的自举的过程。

在这里插入图片描述

编译器的自举是指能够直接或间接地编译自己的编译器
实现自举的过程中,开发者需要用目标语言编写一个简易版本的编译器。接着利用已有的编译器(可能是另一个语言的编译器)来编译这个新编写的编译器。然后,使用新编译出来的编译器去编译和完善原先的源代码,不断迭代这个过程,直到编译器能足够处理自身语言的复杂性。
程序翻译的过程,就是从其他语言翻译为计算机能够识别二进制语言的过程,和上面的语言发展方向相反。

1.3.2. 预处理(语言种类不变)

预处理功能主要包括

  • 头文件展开:将头文件部分内容拷贝到源文件,有对应的拷贝条件
  • 宏替换
  • 条件编译
  • 去注释
    预处理指令是以#号开头的代码行。

在这里插入图片描述


 gcc –E test.c –o test.i

选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序


条件编译用途:

应用:

  • 对软件的专业版、普通版,这些功能不同的版本进行裁剪,实现功能的不同。
  • 防止头文件被重复包含
    我们可以通过给编译器传递不同的宏值,来进行对代码的动态裁剪。
gcc test.c -o test -D VERSION1=1

在这里插入图片描述
在这里插入图片描述

1.3.3. 编译(生成汇编语言)

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

gcc -S test.i -o test.s

用户可以使用-S选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
-o选项是指目标文件,“ .s ”文件为已经过翻译的原始程序。

1.3.4. 汇编(生成二进制文件)

把上阶段的汇编文件,转为二进制(可重定位目标二进制文件)。

注意:该文件是不能够执行的**。**

gcc –c test.s –o test.o

-c选项可以得到汇编代码转化为“.o ”的二进制目标代码。

1.3.5. 链接

链接的主要任务就是将生成的各个“ .o ”文件进行链接,与系统中的库建立联系,生成可执行文件。

gcc/g++不带-E、-S、-c选项时,就默认生成预处理、编译、汇编、链接全过程后的文件。

gcc test.o –o test

若不用-o选项指定生成文件的文件名,则默认生成的可执行文件名为a.out。

2. 函数库

在我们编写代码时时常需要使用库函数中的函数,比如stdio.h中的printf函数,但当我们展开stdio.h文件后发现也只是有printf的函数声明,那么这些库函数的定义放在哪里了呢?

2.1. ldd 查看可执行文件的使用的函数库

查看的是动态链接,形成的可执行文件,依赖的共享库

ldd 可执行文件

在这里插入图片描述

就以stdio.h头文件举例,里面的库函数实现在了名为libc.so.6(C标准库)的库文件中。在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现printf函数了,而这也就是链接的作用。
在这里插入图片描述

平台要支持开发,就必须要提前在系统中安装 语言的标准头文件+库文件!

3. 动静态库

  • 库分为动态库与静态库
    • 在linux中,动态库文件以.so结尾, 静态库以.a结尾。
    • 在windows中,动态库文件以.dll结尾, 静态库以.lib结尾。
      动静态****库本质就是一个文件,里面包含了很多已经被编译好的代码。

3.1. 动静态库定义

静态库:

指编译链接时,把库文件的代码全部加入到可执行文件当中,因此生成的文件比较大,但在运行时也就不再需要库文件了,静态库一般以.a为后缀。

动态库:

在编译链接时并没有把库文件的代码加入到可执行文件当中,而是在程序运行时由链接文件加载库,这样可以节省系统的开销,动态库一般以.so为后缀。


3.2. 动静态库的优缺点

  • 动态库(链接方式:动态链接)

    • 优点:比较节省资源,不会出现太多的重复代码 。
      • 资源:磁盘,内存,网络等资源(例如:写了一个项目,里面有多个文件,这里文件中调用了很多个库里面的函数,虽然调用了很多函数,但是实现就只有一个,不会造成代码冗余的问题)
    • 缺点:对库的依赖性强,一旦库出现问题,那么所有使用了该库的程序全部都无法运行。
  • 静态库(链接方式:静态链接)

    • 优点:不依赖库(因为静态链接是将库文件代码直接拷贝到可执行文件中),可以在同类型平台中都直接运行。(同类型平台:都是Ubuntu)
    • 缺点:体积比较大,比较浪费资源,会出现太多的重复代码 (资源:磁盘,内存,网络等资源。)

3.3. 如何切换使用动静态库

动态链接:gcc -o 可执行程序名称 源文件(gcc默认使用动态链接)

静态链接:gcc -o 可执行程序名称 源文件 -static

在这里插入图片描述

如果想要使用静态链接?就需要 先安装 静态库
C/C++静态库的安装:命令

sudo yum install glibc-static libstdc++-static

file查看可执行文件的链接方式

在这里插入图片描述

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值