【Linux】 gcc 、动态库和静态库,程序是如何链接的

news/2024/7/8 2:06:16

文章目录

  • 前言
  • 一、gcc 是什么?
  • 二、使用步骤
    • 1.预编译
    • 2.编译
    • 3.汇编
    • 4.链接
  • 三、动静态库
    • 1.概念
    • 2.区别


前言

  在Linux环境下,除了学好编辑器 vim 的使用,还需要学会C语言的编译器 gcc 的功能,否则代码无法翻译成可执行程序。本文将介绍 gcc 的常规使用方法,以及一个C语言程序,在链接的时候发生了什么。


提示:以下是本篇文章正文内容

一、gcc 是什么?

  GCC原名为GNU C语言编译器(GNU C Compiler),只能处理C语言。但其很快扩展,变得可处理C++,后来又扩展为能够支持更多编程语言,如Java、Go等等。其作用就是,将一个C语言文件,执行翻译的过程,从 .c 文件变成 .exe 文件,这样就可以执行( .c 文件只存放代码,相当于记事本)。可以看这篇文章,了解翻译的过程:你知道.c文件是如何变成.exe文件的吗。

  翻译过程可以大致分为:预编译、编译、汇编、链接。在链接期间,涉及到链接器的一些小知识,本文也会讲解。


二、使用步骤

1.预编译

  在 Linux 中输入指令如下,其作用主要包括:宏定义,文件包含,条件编译,去注释等

gcc -E test.c -o test.i

  • 选项“-E”,该选项的作用是让 gcc 在预编译结束后停止翻译过程。
  • 选项“-o”是指目标文件(所以它后面跟的是想要生成的文件名), “.i” 文件为已经过预处理的C原始程序。

  如下图:
请添加图片描述

2.编译

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

gcc -S test.i -o test.s

  • 选项“-S”,该选项只进行编译而不进行汇编,生成汇编代码

  如下图:
请添加图片描述

3.汇编

  在 Linux 中输入指令如下,其作用是:把编译阶段生成的“.s”文件转成目标文件

gcc -c test.s -o test.o

  • 选项“-c”,该选项将汇编代码已转化为“.o”的二进制目标代码。

  如下图:
请添加图片描述

4.链接

  在 Linux 中输入指令如下,其作用是:合并符号表、合并段表等等

gcc test.o -o test

  如下图,可以很明显地看到,生成了一个可执行文件test。

请添加图片描述
  当然了,上面只是为了理解翻译过程,但是其实可以一步到位生成可执行文件,那就是 gcc test.c -o test 可以将 test.c 文件生成 可执行文件 test。 当然,最简单的做法是 gcc test.c 但是这样无法控制生成的文件名,其默认目标文件名是 a.out 。


三、动静态库

1.概念

  在上文内容其实涉及到一个重要概念:函数库。
  库分为两种:静态库和动态库。其命名规则是:前缀+文件名+后缀。如下图,静态库后缀是.a ,动态库后缀是 .so,其前缀都是 lib 。

静态库:libXXXXX.a
动态库:libXXXXX.so

  我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?
  实际上是:Linux系统把这些函数实现都被做到名为 libc.so.6 (Linux默认使用动态库)的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。

2.区别

  我们先看到动态库:他是专门让编译器,对用户的程序进行动态链接的。
  动态链接:链接的时候,找到动态库,拷贝动态库中的我所需要的代码的地址到我自己的可执行程序中相关的位置。
  动态链接成功:我们的程序,还是依赖动态库,一旦动态库缺失,我们的程序便无法运行!
  我们根据上面使用 gcc 的示例文件test,如下,先执行 ldd test,查看其依赖库,是 libc.so.6 此时就可以看出是依赖动态库了;再执行 file test,查看其信息可得,确实Linux 默认使用动态库。
在这里插入图片描述


  静态库是专门让编译器,对用户的程序进行静态链接的。
  静态链接:链接的时候,找到静态库,拷贝静态库中的我所需要的代码到我自己的可执行程序中。
  静态链接成功:我们的程序,不依赖任何库,自己就可以独立运行
  如下,我们使用静态链接的方法生成 test-static 文件,从两个箭头指向的地方,可以明显看出,test-static 比 test 大了百倍,其仅仅是一个打印 Hello World 的程序生成,区别如此之大。再用 ldd 指令查看,不是动态的,file 指令查看详细信息,静态链接。(注意,编译此程序需要用到libc库文件,而系统中无法找到libc的静态库文件,需要下载安装:sudo yum install -y glibc-static)
在这里插入图片描述

  根据以上内容,可以得出结论:

静态库:因为自身拷贝的问题,比较浪费空间。
动态库:因为可以做到被大家共享方法,所以真正的实现永远都是在库中,程序内部只有地址,比较节省空间。

   Linux默认使用的是动态链接和动态库!如果进行大型项目开发,其文件非常巨大,如果使用静态库,其所消耗空间资源比动态库要多上接近一百倍,所以使用动态库更好一些。



http://lihuaxi.xjx100.cn/news/633562.html

相关文章

【JavaSE系列】第十节 —— 带你吃透抽象类

(6)当一个抽象类 继承一个抽象类的时候,可以不用来重写 当作父类的那个抽象类的抽象方法:提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、抽象类的概念 二、…

数据结构(2)树状数组

活动 - AcWing 参考:《算法竞赛进阶指南》-lyd 目录 一、概念 1.主要功能 2.实现方式 3. 二、例题 1.树状数组和逆序对 2.树状数组和差分 3. 两层差分 4. 结合二分 一、概念 1.主要功能 树状数组可以完成的功能主要有: 维护序列的前缀和单…

唤醒手腕 Go 语言开发学习笔记(基本简介、环境安装、基础知识)

1. Go语言简介 Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收&#xf…

研究发现,大多数长期 COVID 影响在感染后一年内消退

英国医学杂志今天发表的一项来自以色列的大型研究发现,轻度 COVID-19 感染后出现的大多数症状或病症会持续数月,但在一年内恢复正常。 特别是接种过疫苗的人,呼吸困难的风险较低。这通常也是轻度感染后最常见的影响。相比之下,比未…

Java线程的六种状态

前言:其实线程的状态在操作系统的PCB中就对其进行了描述,但是Java中觉得自带的状态并不是特别好,于是引入了线程在Java中的六种状态。 (1) NEW 安排了工作还未行动,即:Thread对象创建出来了,但是内核的PCB…

一文读懂Go Http Server原理

hello大家好呀,我是小楼,这是系列文《Go底层原理剖析》的第二篇,依旧是分析 Http 模块,话不多说,开始。从一个 Demo 入手 俗话说万事开头难,但用 Go 实现一个 Http Server 真不难,简单到什么程度?起一个 Server,并且能响应请求,算上包名、导入的依赖,甚至空行,也就…

Java多线程:线程的优先级 || 线程的中断 || 线程的分类 || 线程的定时器

Java多线程:线程的优先级 || 线程的中断 || 线程的分类 || 线程的定时器 每博一文案 正如村上春树所说:“当暴风雨过去,你不会记得自己是如何度过的,你甚至不确定,暴风雨是否真正结束了, 但你已不再是当初…

Java异常情况了解

作者:爱塔居的博客_CSDN博客-JavaSE,数据结构领域博主 专栏:JavaSE 作者介绍:大三学生,希望一起进步~ 文章目录 目录 文章目录 一、异常结构体系 二、异常分类 三、异常处理 3.1异常抛出 3.2 异常捕获 四.【面试题】 五、题目练习…