【Linux学习笔记】代码编译工具gcc/g++

news2024/11/26 16:57:06

  • 1. 程序的翻译
    • 1.1. 预处理
    • 1.2. 编译
    • 1.3. 汇编
    • 1.4. 链接
  • 2. 动态链接和静态链接
    • 2.1. 动态链接
    • 2.2. 静态链接
    • 2.3. 动态链接和静态链接的区别
    • 2.4. 动态链接和静态链接的验证
  • 3. make/makefile
    • 3.1. 依赖方法和依赖关系
    • 3.2. 写一个makefile文件
    • 3.3. PHONY的意义
    • 3.4. makefile的推导规则
  • 4. Linux下的第一个小程序
    • 4.1. 缓冲区概念
    • 4.2. 小程序代码

1. 程序的翻译

在Linux中,gcc/g++是一个c/c++编译器。下面我们从程序的翻译过程来了解gcc工具的应用。程序的翻译分为以下的4步:

  1. 预处理
  2. 编译
  3. 汇编
  4. 链接

1.1. 预处理

程序翻译的第一步,就是做预处理工作。在Linux中,我们可以利用gcc创建一个文件来查看预处理的过程。

命令: gcc -E 文件名 -o 你想取的文件名

功能:翻译一个文件,当做完预处理阶段,就停下来。 -o选项是生成临时的文件。

示范:

img

其中,我们要知道程序翻译的过程中,预处理部分是做了什么工作的?

  • 程序的预处理:
  1. 头文件展开
  2. 去注释
  3. 宏替换
  4. 条件编译

那么我们知道了预处理是做了以上工作的,我们来打开test.i文件看看是不是这样的?

img

img

我们可以看到,通过gcc工具,输入相应的指令,我们可以看到程序翻译的预处理部分。

1.2. 编译

编译的工作主要是把C语言转换成相应的汇编语言。下面我们通过gcc工具来看一看过程。

命令: gcc -S 文件名 -o test.s

功能: 从现在开始,进行程序的翻译,做完编译工作,变成汇编之后,就停下来。

示范:

img

打开新形成的文件,我们可以看到里面的一些汇编代码。

img

1.3. 汇编

汇编这一步的主要功能就是将汇编代码变成二进制文件(不可执行)。

命令: gcc -c 文件名 -o test.o

功能:从现在开始,进行程序的翻译,完成汇编工作后,形成一个不可执行的二进制文件

示范:

img

打开test.o文件,我们可以看到里面的内容。

img

1.4. 链接

链接这一过程结束后,就形成了可执行程序(可执行的二进制程序)。主要内容就是库 + 你的代码。

命令: gcc 文件名 -o 你想取的文件名

功能:将汇编的文件与库链接,形成可执行的二进制程序。

示范:

img

通过执行该文件,我们可以相当于完成了程序的翻译。

img

2. 动态链接和静态链接

2.1. 动态链接

在日常的一天,你对自己接下来的一整天都做了一份计划,例如,吃早餐,看书,看剧,…

你是一名高中生,家里没有电脑,但是你这时候给自己的安排是打电脑游戏。那怎么办呢?

办法当然是去网吧咯,在网吧里,里面的机子都可以满足你对电脑的需求。

那么把角度切换回程序的世界。你对你接下来的一整天都做好的计划就是你的程序,当你的程序运行到打电脑游戏的时候,你才会动身去网吧使用电脑。

就好像你的代码需要某个功能的实现,例如打印,刚好库里printf就能实现你的需求。

这个动态就类似让你动起来。

img

其中你是怎么知道网吧的位置呢?那肯定是找人问的咯。同样的,切换回程序的世界,程序是怎么知道库的存在呢?答案是编译器的存在,编译器可以认为是你找网吧时问的那个人,通过那个人你找到了网吧,程序通过编译器找到了标准库。

2.2. 静态链接

回到上面的例子,某一天父母发现你对电脑的需求,所以在家里给你配了一台电脑,从此以后你用电脑的时候就不再需要跑去网吧了,而是在家使用电脑。切换回程序的世界,当你自己亲手写了一个函数,当你的程序运行到某一步时,就不需要调用标准库里的函数,而是直接可以使用你写的代码。

img

2.3. 动态链接和静态链接的区别

  • 动态链接
  1. 如果一个网吧要升级,你觉得你还能去上网吗?答案肯定是不能的。同样的道理,如果一个库要升级,你就不能使用这个库的代码了。
  2. 如果网吧被取缔了,那么你就没得上网咯。同样的,如果一个库被取缔,你也不能使用这个库的代码了。
  3. 从你家里到一家网吧是需要一段路程的,那么也就是说是要花费时间的。同样的,动态链接也是需要时间的。

动态链接的优势:

  1. 形成的可执行程序小,主要体现在内存,磁盘,网络方面。如果你的软件程序体积小,那么内存加载就会快;同样的在磁盘中所需要占用的空间也小;同样的网络上下载文件,如果体积小,那么下载的速度也会快很多。就好比你去网吧,在电脑方面上的东西,你基本都不用带,人过去就行;切回代码的角度,就是你直接调用库代码即可。
  • 静态链接
  1. 家里有电脑,我根本就不关心网吧要不要升级。同样的,我自己写了一个代码,跟库里的一模一样,那么我就用自己的代码就好啦。
  2. 网吧被取缔了,机器都没了,但是与我无关,因为我有家里的电脑。如果因为某些原因,不小心把库给删除了,我依旧能用我的代码。
  3. 时间问题,由于我家里有电脑,我根本就不需要出门,所以时间上的花费就少了很多。

静态链接的优势:

  1. 不受库的影响,种种优点就是上面所说的。但缺点也明显,就是形成的可执行程序体积太大!

2.4. 动态链接和静态链接的验证

  1. 动态库在Linux下的命名

一般是libXXXXXX.so,其中lib是前缀,.so是后缀,去掉前缀和后缀,中间的就是库的名称。

  1. 静态库在Linux下的命名

一般是libXXXXXX.a,其中lib是前缀,.so是后缀,去掉前缀和后缀,中间的就是库的名称。

  1. 使用ldd + 文件名即可查看你文件中的代码使用了哪个库。

动态链接的验证

file + 可执行程序的文件名即可查看文件的链接方式。

img

其中你也可以在使用gcc工具对文件进行编译的时候,指定文件使用静态链接。操作如下:

img

img

3. make/makefile

make是一个命令,makefile是一个文件。

用一个例子来解释,就好比厂里有一台机子,你在操作台上面提前设置好动作,让机器实现自动化。

切换会代码的角度,就是创建好一个makefile文件,里面的内容是关于你接下来的动作,例如编译代码。

img

img

makefile文件中的指令:

img

3.1. 依赖方法和依赖关系

用生活中的例子来解释,假如你是一个学生,你生病了要请假,那么就要向班主任说明你的情况并作出申请,然后班主任同意了即可请假离校。其中学生和班主任是依赖关系,你一个学生总不能向你的好基友请假吧。所谓的依赖方法就是请假的程序,向班主任申请,班主任同意,离校…

切换回代码的角度,我要形成可执行程序,我要依赖源文件。依赖方法就是我接下来要怎么做,其中上图的依赖方法可以看到,我是要用gcc工具来编译形成可执行程序。

3.2. 写一个makefile文件

如何编写一个makefile文件呢?

  1. 在第一行中,冒号是关键(:) ,冒号的左边是形成的目标文件,冒号的右边是依赖文件(可有可无)
  2. 在接下来的第二行,先有一个table的间隔,然后开始编写依赖方法。
  3. 如图所示:

img

img

3.3. PHONY的意义

我现在写好了一个伪目标makefile文件如下:

img

上面的test没有用PHONY修饰,那么只要vim里面的代码没有任何改动,那么make命令就不会执行。如下:

img

但是用了PHONY修饰的指令,会一直执行。如下:

img

我把test也加上PHONY修饰。

img

执行make命令如下:

img

那么g++是怎么知道文件到底更没更新呢?先来认识一下文件的三个时间

img

其中make命令就是根据依赖的文件与目标文件形成时间的先后来判断是否需要更新。

3.4. makefile的推导规则

首先我们看到上面的makefile的文件内容是直接生成可执行程序的,但是可执行程序是怎么来的呢?同样的也是经过程序的翻译才能得到的可执行程序。所以根据刚才所说的,我们可以知道实际的makefile内容应当是这样的:

img

  1. 先依赖test.o文件,但是没有,所以进入到下一层找
  2. 依赖test.s文件,没有,进入下一层
  3. 依赖test.i文件,没有,进入下一层
  4. 依赖test.c文件,有,形成test.i文件
  5. 形成test.i文件后,逐一返回上层执行命令。

img

一句话总结,你可以理解为是数据结构中的栈结构,也就是先进后出。

4. Linux下的第一个小程序

4.1. 缓冲区概念

下面来看两个代码

img

img

其中代码的不同就是少了一个换行符,在语言层面,换行符其实就相当于行缓冲。

第一个代码因为有了行缓冲,所以printf里面的内容直接被刷新。所以是先打印内容,再等待2s。

第二个代码因为没有行缓冲,所以printf里面的内容没有直接被刷新,而是先等待2s,然后再从缓冲区里面打印出来。

4.2. 小程序代码

利用上面的缓冲区概念,我们可以利用这个特性,做出一个倒计时的小程序。

1 #include "process.h"
  2 void Process()
  3 {
  4     char s[NUM];
  5     memset(s,'\0',sizeof(s));
  6     int cnt = 0;
  7     char ch[4] = {'|','\\','/','-'};
  8     while(cnt <= 100)
  9     {
 10         printf("[%-100s][%d%%][%c]\r",s,cnt,ch[cnt%4]);                                                                                                             
 11         fflush(stdout);
 12         s[cnt++] = STR;
 13         usleep(50000);
 14     }
 15     printf("\n");
 16 }

效果可以自行运行代码查看,很有趣的小程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1097225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu:VS Code IDE安装ESP-IDF【保姆级】(草稿)

物联网开发学习笔记——目录索引 Visual Studio Code&#xff08;简称“VS Code”&#xff09;是Microsoft向开发者们提供的一款真正的跨平台编辑器。 参考&#xff1a; VS Code官网&#xff1a;Visual Studio Code - Code Editing. Redefined 乐鑫官网&#xff1a;ESP-IDF …

[网站部署03]宝塔+worldPress部署Ripro主题网站

1.下载好主题网站上传到下方目录即可 下载地址&#xff1a;请自行百度搜索&#xff0c;官网收费 下载好压缩包上传到/www/wwwroot/你的网站目录/wp-content/themes 2.回到Worldpress后台点击外观可以看到主题网站 http://192.168.49.128/wp-admin/themes.php 剩下的就是设置…

【matlab海洋专题】高级玫瑰图--风速风向频率玫瑰图--此图细节较多

玫瑰图分享过好多 这一次的还是不一样&#xff0c;细节较多 本期内容 【matlab海洋专题】高级玫瑰图–风速风向频率玫瑰图–此图细节较多: 总结起来&#xff0c;确实不好画&#xff01; 图片如下&#xff1a; 图片名称我不知道&#xff0c;我意会为&#xff1a; 风速风向…

众和策略:国际油价走高,石油板块强势拉升,通源石油、和顺石油等涨停

石油板块16日盘中大幅拉升&#xff0c;到发稿&#xff0c;通源石油、和顺石油、贝肯动力、中曼石油、泰山石油、仁智股份等涨停&#xff0c;潜能恒信、博迈科涨约8%。 燃气板块亦上扬&#xff0c;到发稿&#xff0c;洪通燃气、美能动力涨约5%&#xff0c;新疆火炬、九丰动力涨…

众和策略:减肥药概念热度不减,百花医药斩获4连板,公司提示风险

减肥药概念16日延续强势&#xff0c;部分个股继续走高。到发稿&#xff0c;博瑞医药涨约11%&#xff0c;百花医药、双鹭药业涨停&#xff0c;金凯生科涨近10%&#xff0c;昊帆生物涨超8%&#xff0c;华森制药、翰宇药业、常山药业等涨超5%。值得留意的是&#xff0c;博瑞医药近…

以任意位置中间元素翻转字符串:

前置知识&#xff1a; 你要学会如何将字符串转化为字符&#xff0c;如何将字符转为字符串 字符串转化为字符 String str "abcdef";char[] strChar str.toCharArray();for(int i :strChar){System.out.print((char)i" ");//需要进行强制类型转换&#x…

迅为RK3588开发板使用RKNN-Toolkit-lite2运行测试程序

1 首先也需要部署运行环境&#xff0c;将库文件放入 RK3588 开发板上&#xff0c;我们将网盘资料“iTOP-3588 开发 板 \02_ 【 iTOP-RK3588 开 发 板 】 开 发 资 料 \12_NPU 使 用 配 套 资 料 \05_Linux_librknn_api\librknn_api\aarch64”路径下的文件通过U盘拷贝到开发板的…

进程相关介绍(二)

进程状态 当我们的进程运行的时候有很多状态&#xff0c;因为我们的CPU资源是有限的&#xff0c;我们的进程必须有选择性的放入CPU上面才可以运行。因此我们的进程就存在了很多种进程状态&#xff0c;比如运行态&#xff0c;阻塞态&#xff0c;挂起态等等。在本次的博客当中我们…

如何选择功放芯片?音质好的功放芯片性能详解

数字功放也称为数字音频功放芯片&#xff0c;是一种利用数字信号处理技术进行音频放大的集成电路芯片&#xff1b;是现代音频放大技术的重要组成部分&#xff0c;广泛应用于音响系统、家庭影院、汽车音响、无线音箱等领域&#xff0c;以实现高质量的音频放大效果。 其工作原理…

优思学院:成功团队的十大秘诀,助你事业腾飞!

在竞争激烈的商业环境中&#xff0c;成功的团队是一个企业腾飞的关键。一个协作默契、高效运作的团队不仅可以提高生产力&#xff0c;还能激发创新&#xff0c;推动企业的可持续发展。那么&#xff0c;到底是什么让一支团队在竞争中脱颖而出呢&#xff1f;本文将为你揭示成功团…

【Linux学习笔记】git工具

1. 仓库克隆1.1. .git ignore文件 2. git的三板斧 1. 仓库克隆 首先打开gitee网站注册一个账号&#xff0c;使用该账号创建一个仓库&#xff0c;然后复制仓库的https地址&#xff0c;然后到xshell使用命令进行仓库克隆。 创建仓库 其中创建仓库&#xff0c;详细的可以去网上搜…

AD20绘制电路板的外形

今天学习了绘制电路板外形的方法&#xff0c;记录一下&#xff0c;回头忘了还能在看看&#xff0c;便能很快的回忆起来了&#xff0c;比看视频啥的要高效的多。毕竟是自己写的&#xff0c;印象要深刻的多。 首先新建一个PCBDoc文件&#xff0c;方法如下图&#xff1a; 在新建的…

电力配电机房监控方案

电力配电机房是电力系统的核心组成部分&#xff0c;对于电力运行和供电质量至关重要。为了确保电力系统的安全和稳定运行&#xff0c;监控机房的关键参数和状态变化变得至关重要。星创易联的4G工业路由器SR500和DTU200是一套先进的解决方案&#xff0c;能够实现对电力配电机房的…

Vue - 快速入门,这一套就够了!(Vue core + 案例 + 效果演示)

目录 前言 一、Vue 基础 1.1、Vue 基础示例 a&#xff09;html 部分&#xff1a; b&#xff09;script 部分&#xff1a; 二、本地应用 1.1、内容绑定&#xff0c;事件绑定 1.1.1、v-text 设置标签文本值 1.1.2、v-html 设置标签的 innerHTML 1.1.3、v-on 为元素绑定…

嵌入式平台的电源总结

本文引注: https://mp.weixin.qq.com/s/PuSxHDFbJjjHEReukLSvyg 1.AC的定义 Alternating Current&#xff08;交流&#xff09;的首字母缩写。AC是大小和极性&#xff08;方向&#xff09;随时间呈周期性变化的电流。电流极性在1秒内的变化次数被称为频率&#xff0c;以Hz为单位…

微服务项目打包部署

目录 1、在父项目上面打包2、部署到服务器上3、进行测试 1、在父项目上面打包 &#xff08;1&#xff09;点击clean&#xff0c;compile&#xff0c;最后点击package进行打包 打包成功&#xff1a; 在target目录下面可以看到jar包 2、部署到服务器上 将项目上传到相应文件下…

非线性负载的常见问题及解决方法有哪些?

非线性负载可能导致负载波动较大&#xff0c;可以使用电压稳定器或电流稳定器来提供稳定的电源供应&#xff0c;或者使用反馈控制技术来调节负载的工作状态。在非线性负载中&#xff0c;可能会出现信号失真的问题&#xff0c;使用线性化技术&#xff0c;如预失真技术&#xff0…

当GDB遇到STL

STL是标准模板库&#xff08;Standard Template Library&#xff09;的简称&#xff0c;是C的三大件之一。 ‍‍ Alex是STL的核心设计者。他于1950年出生在莫斯科&#xff0c;后来到美国发展&#xff0c;曾经在Adobe、A9.com等公司工作。在Adobe工作时&#xff0c;他和保罗•麦…

前端技术-并发请求

并发请求 代码解释 定义了一个函数 concurRequest&#xff0c;用于并发请求多个 URL 并返回它们的响应结果。 function concurRequest(urls, maxNum) {return new Promise((resolve, reject) > {if (urls.length 0) {resolve([]);return;}const results [];let index …