当前位置: 首页 > news >正文

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

欢迎拜访:Madison-No7个人主页
文章主题:gcc/g++编辑器 && 初识动静态库 && 程序翻译过程
隶属专栏:从0到1掌握Linux
写作日期2025年10月21号

目录

前言:

一、预处理:

预处理阶段的功能:

二、编译(生成汇编):​编辑

编译阶段的功能:

三、汇编(生成机器可识别的代码):

汇编的功能:

四、链接(生成可执行文件或库文件): 

链接的功能:

4.1 什么是库?

4.2 目标文件和库是如何链接的?

4.2.1 静态链接:

4.2.2 动态链接:

4.3 动静态库的对比:

示例:

再谈动态库:


前言:

我们使用 Vim 编辑器编写的代码只是文本文件,要让代码运行起来,就需要借助 gcc 和 g++ 编译器。这两个工具分别用于编译 C 和 C++ 程序。下面我将为大家介绍它们如何完成代码的编译过程。

gcc/g++编译选项:

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

写好的test.c源文件:

该程序需要经过翻译过程生成可执行文件,才能执行代码。

也可以跳过翻译过程,直接生成可执行文件。

📌 翻译过程是由编译和链接两个大的过程组成,而编译又可分解成:预处理、编译、汇编三个过程。

一、预处理:

将test.c文件进行预处理,生成test.i预处理文件-----gcc –E test.c –o test.i

选项“-E”:开始进程程序翻译,在预处理做完的时候,就停下来。

“.i”⽂件为已经过预处理的C原始程序。

选项“-o”是指定写到test.i文件里面,如果不加选项-o,就直接打印到下面。

vim test.i    -----打开test.i文件

预处理阶段的功能:

在预处理阶段,编译器会将头文件内容(头文件中只是一些函数的声明)展开并拷贝到test.i文件中,同时执行以下操作:去除注释、替换宏定义以及处理条件编译指令。

🌟条件编译的用途?

1.同一套代码可能需要支持不同功能版本(如社区版、专业版),或根据客户需求启用 / 禁用特定模块,条件编译可通过宏定义快速切换。

2.内核源代码也是采用条件编译进行动态裁剪。

3. 开发工具,应用软件适配不同平台。

gcc test.c -o test -DM    ------其中的-DM意思是#define M->插入到代码中,也就是说可以进行命令行级别的宏定义。

🌟预处理的本质:

让编译器编辑修改我们的代码,把不需要去掉,把需要的加上,但是还是C语言,只不过和我们的源码相比变得更干净了。

二、编译(生成汇编):

将预处理文件进行编译,生成汇编代码-----gcc -S test.i -o test.s

“-S”的作用是:开始生成汇编代码,生成完了,就停下来。
“.s”,常为汇编代码的后缀。
vim test.s    ----打开test.s文件

编译阶段的功能:

gcc ⾸先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的⼯作, 在检查⽆误后,gcc 把代码翻译成汇编语⾔。

📌 为什么C/C++编译,要先变成汇编代码?

首先要明白计算机的硬件核心只能识别二进制,这是由半导体电路的二态性决定的;其他进制(十进制、十六进制等)是为了方便人类使用而设计的 “抽象层”,最终都会被转换为二进制信号才能被硬件处理。所以我们所写的程序,最后都要转化为机器语言(二进制)才能被计算机硬件处理。

三、汇编(生成机器可识别的代码):

将汇编文件转成目标文件(二进制)-----gcc -c test.s -o test.o

“-c”:只进行编译(Compile),不进行链接(Link),最终生成目标文件(Object File)而非可执行文件。

“.o”:目标文件(Object File),是二进制文件

vim test.o 

汇编的功能:

将汇编语言的.s文件转化为机器指令,生成后缀为.o(Windows 下为.obj)的目标文件。

注意:生成的目标文件是二进制文件,还不能直接运行,因为它缺少程序运行所需的外部资源,比如我们写的test.c源文件中用到了printf函数,汇编过程只是把我们写的代码转化成了机器指令,对于printf函数,它的定义是在C语言标准库里面,它并没有转化为机器指令,所以我们还要经过链接:将多个目标文件和所需的库文件组合,生成可执行文件(Windows 下为.exe,Linux 下为无后缀的可执行文件)。

📌 小Tips:

如何记忆gcc编译选项:-ESc 就是键盘左上角的按键Esc,只需要记住前两个字母是大写的。

如何记忆编译过程所形成的临时文件后缀:.iso  可以理解成镜像文件

四、链接(生成可执行文件或库文件): 

链接的功能:

多个目标文件(.o文件)和所需的库文件组合到一起,生成可执行文件(Windows 下为.exe,Linux 下为无后缀的可执行文件)。

其实对于库文件无论是静态库还是动态库(共享库),本质上都是由多个目标文件(.o 文件)“打包” 组合而成的集合。关于如何“打包”形成库,以后会讲解到。

📌 我们往往喜欢的是把多个源文件编译成对应.o二进制文件,再把这些.o文件合并到一起,形成可执行文件。为什么呢?

因为对一个大型程序来说,可能有成百上千个.c源文件组成,如果直接编译成可执行文件,每次修改任意一个源文件,编译器都需要重新编译所有文件,这在文件数量多、代码量大时会极其耗时(例如一个包含 100 个文件的项目,改一行代码就要重新编译 100 个文件)。而先编译成.o目标文件时,只有被修改的源文件会重新编译,未修改的文件只需复用已生成的.o文件。最后通过链接器将所有.o文件组合成可执行文件,大幅减少重复劳动。这就像盖房子:先预制好门窗、墙体(.o文件),哪部分坏了只换哪部分,而不是每次都推倒重盖。

🌟上面提到了库文件,那什么是库文件呢?

库文件(Library File)是存储可复用代码(函数、类、数据结构等)的物理文件,是 “库” 这一抽象功能集合的具体载体。它包含编译后的二进制代码,供其他程序调用,以实现代码复用和功能扩展。

上面所写的test.c源文件,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,⽽没有定义函数的实现,那么,是在哪⾥实现“printf”函数的呢? 答案是:系统把这些函数实现都被放到名为 libc.so.6 的库⽂件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进⾏查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也是链接的作⽤。

ldd + 可执行文件,可以查看可执行文件依赖了哪些库文件。

ldd +/usr/lib+指令,可以查看这些指令依赖了哪些库。通过上图可以看出ls、mkdir指令也依赖了libc.so.6库,也就是说Linux的指令也是由C语言写的。

🌟注意:

libc.so.6是 Linux 系统下的 C 语言标准库(GNU C Library,简称 glibc)的动态库文件,是绝大多数 Linux 程序运行的核心依赖。几乎所有 Linux 下的 C 程序(包括系统命令如 ls、mkdir)都依赖libc.so.6。如果这个文件损坏或丢失,系统会直接报错,甚至无法正常启动。

4.1 什么是库?

库(Library) 是一组预先编写好的代码集合,包含可复用的函数、类、数据结构或其他程序组件,目的是帮助开发者快速实现常见功能,避免重复造轮子,提高开发效率。

库分为静态库和动态库?

  • 静态库是编译好的二进制代码集合,在程序编译的 “链接阶段” 会被完整复制到目标程序中,成为可执行文件的一部分。
  • 动态库是独立存储的二进制代码文件,程序编译时不会被复制到可执行文件中,仅在程序运行时被加载到内存并供程序调用,多个程序可共享同一份动态库。

注意:

Linux下,动态库XXX.so, 静态库XXX.a

Windows下,动态库XXX.dll, 静态库XXX.lib

我们在命名自己所写的库时,比如写了一个xyz库,命名时要加上lib前缀,后缀(不同平台下不一样)。以Linux下为例,可命名为libxyz.so。

4.2 目标文件和库是如何链接的?

总体上,链接分为两类:动态链接静态链接

4.2.1 静态链接:

把我们程序中使用的库方法,拷贝给我自己!静态库就像电脑商城,当有人有上网需求时,会到电脑商城去买一台专属的电脑,只供自己使用。此外静态库只有在链接时有用,一旦形成可执行程序,静态库可以不再需要了。

4.2.2 动态链接:

程序编译时,链接器仅在可执行文件中记录动态库的依赖信息(如库文件名、函数名),不复制库代码;程序运行时,由操作系统加载动态库并解析函数地址。动态库就像是一个网吧,任何人想上网了,都可以去到这个网吧里。即:动态库是被所有程序所共享的,一般也被叫做共享库。这意味着,动态库只需要一个就够了,它可以满足所有程序的需求。

4.3 动静态库的对比:

1.动态库所形成的可执行程序体积一定很小。

2.可执行程序对静态库的依赖小,动态库不能缺失。

3.程序运行时,需要加载到内存,通过静态链接的程序,会在内存中出现大量重复的代码。

4.动态链接比较节省资源。

示例:

以test.c代码为例:

ldd test 查看依赖哪些库

所以gcc编辑器默认实行动态链接的。

file +可执行文件:查看具体可执行程序的信息。

同时动态链接形成的可执行文件大小:

如果非得要通过静态链接生成可执行文件:

需要在最后加上-static。

同时静态链接形成的可执行文件大小:

此外C++所以依赖的动态库是:libstdc++.so.6


再谈动态库:

动态库的代码段只需加载一份到内存,多个依赖它的可执行文件通过动态链接共享这份代码;动态库不能丢失,就像网吧被查封了,人们就不能去上网一样。一旦对应的动态库丢失,影响的不只是一个程序,可能会导致多个程序都无法正常运行。


完。

今天的分享就到这里,感谢各位大佬的关注,大家互相学习,共同进步呀!

http://www.dtcms.com/a/515221.html

相关文章:

  • AI服务器工作之系统下查看硬件(ubuntu为例)
  • 基于python智慧医疗问答系统 知识图谱 Flask框架 数据可视化 neo4j图数据库 计算机专业 优秀项目(源码)✅
  • P3957 [NOIP 2017 普及组] 跳房子
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段-二阶段(6):文法運用
  • 【数据结构入坑指南】--《层序分明:堆的实现、排序与TOP-K问题一站式攻克(源码实战)》
  • 做网站的公司怎么推销湘潭做网站价格 q磐石网络
  • 用Python Streamlit sqlite3 写一个简单博客
  • 微型计算机接口与原理笔记
  • 大学生免费ppt网站广州分销商城开发
  • 良策金宝AI定制方案:构建企业专属的“工程智能体”
  • docker 容器web站点 中文文件名访问404问题
  • 【第五章:计算机视觉-项目实战之推荐/广告系统】2.粗排算法-(1)粗排用来干什么?“我大体筛一下“
  • FDAbench-Full 数据代理任务基准:Python 使用路径
  • HarmonyOS之启动应用内的UIAbility组件
  • 【开题答辩全过程】以抖音热点与可视化分析为例,包含答辩的问题和答案
  • SONiC控制面 + VPP数据面:AsterNOS-VPP的高性能开放之路
  • 未来之窗昭和仙君(二十八)商业收银开发音频播放——东方仙盟筑基期
  • 自助网站系统上海网站建设公司网站建设
  • 杭州网站设计推荐柚米莆田做外贸网站
  • Rust 枚举类详解
  • UU远程——让工作、学习、娱乐跨设备无缝衔接,“远程”更像“身边”
  • 关于模型结构与参数的文件类型及运行设备
  • 一种基于STL-LSTM混合模型的低轨卫星钟差短期预报方法
  • 【Docker】[特殊字符] Docker 部署完全指南 - 从本地开发到云服务器
  • 宝塔面板部署Django:使用Unix Socket套接字通信的完整教程(附核心配置与问题排查)
  • 广西建设局建设行政主管部网站资源网站优化排名软件公司
  • 基于Vue的2025年哈尔滨亚冬会志愿者管理系统5zqg6m36(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 软件可用性测试历史概念✅软件可用性测试的国际标准✅软件可用性测试方法
  • 深入 JavaScript 对象与代理模式的本质、应用与区别!
  • 响水网站制作公司平顺网站建设