一文入门gcc

news2024/11/25 5:32:16

今天我们来玩玩gcc。

是因为突然发现ESP-IDF用的是CMake,要了解CMake最好就要先学习Makefile有个基础,学习Makefile最好就要先熟悉gcc,所以就有了今天这篇文章。

首先我们要明确一个问题,那就是gcc/g++是什么,它们有什么用。

gcc 是 GNU Compiler Collection(GNU 编译器集合)的缩写,是一个用于编程语言的编译器,特别是 C、C++、Fortran、Objective-C、Objective-C++、Ada、Go 以及其他一些语言。它最初是为 GNU 操作系统开发的,但如今已被广泛应用于各种 Unix-like 系统(包括 Linux)和其他操作系统(如 Windows,通过 MinGW 或 Cygwin)。

gcc 的主要用途是将源代码(例如 C 或 C++ 代码)编译成机器代码(通常是可执行文件或库)。它支持多种优化选项和调试选项,使得开发人员能够根据需要调整编译过程。

简单来说gcc就是编译器,它可以将我们写的.c文件变成.exe的可执行文件(当然了,不止.c文件,可执行文件的后缀也不一定是.exe)。

而g++也属于gcc,不过是专门为了编译C++而产生的特化版本。

由于大家初学C语言的时候,大概率是看着教学视频学的,并且视频里一般都是教大家下载IDE,在IDE里进行编程的,因此我们不需要去关注具体是如何使用编译器去编译我们的c文件的。但是到了Linux环境下,就没有那么轻松了(虽然Linux也可以下载安装IDE,但是很多情况下我们用的不是有图形界面的Linux,而是命令行,这样也比较帅对叭),我们需要手动敲命令去对我们写好的程序进行编译。

安装gcc

那么第一步,我们需要先安装上gcc。

我们打开虚拟机,或者你有服务器可以远程连接上也可以,再或者你远程连接你的虚拟机也OK。

我这边以Ubuntu为例(因为手头上安装的虚拟机是Ubuntu的)

我们在命令行里输入下面这个命令

sudo apt-get install gcc

如果成功下载,那么我们可以直接进入下一步。

如果下载不了,显示没有这个软件包,那么我们需要加个源。

执行下面的命令去修改源列表文件。

vim /etc/apt/sources.list

添加一行下面这个内容(不会用vim的小伙伴在上面那个命令执行过后按下i键,然后用上下左右键移动到文件的最下面,然后将下面的复制进去,接着按下esc键,再打个 :冒号,然后输入qw保存退出,如果显示权限不够那就出去改个权限。)。

deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main universe

下一步更新源。

sudo apt-get update

更新完之后下载gcc。

sudo apt-get install gcc

再输入下面命令查看gcc版本,如果能正常看到那么就表示我们下载成功。下载g++的话只需要把上面下载命令中的gcc替换成g++即可。

gcc -v

编译的流程

接下来我们来了解一下.c文件是如何变成.exe文件的。

一共是四个步骤,分别是预处理,汇编,编译,链接。曾经VS帮我们做好了一切,如今我们需要还我们欠下的债了,深刻理解这四个步骤也有助于我们理解我们自己写下的代码(没错,就算是你自己写的代码你也不一定能够彻底明白,反正我上星期写的代码我这星期已经看不懂了)。

预处理

预处理这一步主要会做下面这些步骤。

  • 代码包含:预处理器处理#include指令,这通常意味着将头文件的内容直接插入到源文件中。
  • 宏替换:所有#define定义的宏都会被展开,即在代码中进行相应的文本替换。
  • 条件编译:处理如#if#ifdef等条件编译指令,这些指令通常用于在不同环境下编译不同的代码路径。
  • 注释删除:预处理器会移除所有注释部分,这些注释对编译后的代码执行没有影响。
  • 生成中间文件:预处理过程后通常会生成一个中间文件(如.i文件),供后续编译过程使用

在gcc中预处理的选项是-E,我们只需要使用gcc -E 这个命令就可以对我们写的.c文件进行预处理了。但是光预处理还没有,我们需要把预处理的结果保存起来,这时候就需要使用-o选项来指定文明存放预处理结果的文件。

使用例子如下。其中test.c是写的.c文件,test.i是预处理结果

 gcc -E test.c -o test.i

然后test.c的内容是下面这样的。

很简单的内容,包含了个头文件,使用宏定义代替了一个打印语句。在main函数里使用宏定义并且用了个打印语句。

经过预编译之后我们得到test.i文件。实际上可以叫任何名字,只需要在上面预编译的命令中修改即可,甚至后缀都不一定非得是 .i ,在Linux中后缀是没有实际作用的,它唯一的作用是对于让人可以通过后缀判断出这个文件是什么类型的,而对于Linux来说,后缀是无所谓有无所谓无的东西。

虽然名字可以随意,但是我们约定俗成的命名规则就是保留.c文件的名字,然后修改后缀。

接着我们看看预处理后得到的test.i是什么内容。

原本很简单的一段代码,经过预处理之后变成八百多行了。

文件开头我们看不懂,我们拉到最下面。

主要看最后面的main函数,里面的宏定义被替换成了printf语句。并且注释也没有了。还将我们的头文件展开了,没错,前面差不多八百行代码就是原文件中的#include <stdio.h>展开后的结果。

这就是预处理。

编译

编译这个步骤会对上个步骤得到的 .i 文件做以下处理,最终生成汇编文件。

  • 词法分析:编译器首先识别出源代码中的每个单词,如变量名、运算符等。
  • 语法分析:之后,编译器解析这些单词组成的语法结构,如表达式、控制结构等。
  • 语义分析:确保所有变量都被正确声明,且操作都是合理的,例如类型检查。
  • 优化:编译器会对中间代码进行优化,以提升执行效率,去除不必要的操作。
  • 生成汇编代码:最终,编译器生成对应的汇编代码文件(如.s文件),此代码是机器语言的低级表示。

gcc中汇编的选项是 -S ,得到的汇编文件的后缀一般我们都给 .s ,所以使用的命令如下。

gcc -S test.i -o test.s

我们可以来查看一下生成的汇编文件。

虽然还是很多,但是已经压缩成48行了。汇编就已经是很接近底层的了。

汇编

  • 代码翻译:汇编器将汇编代码转换成机器码,生成目标文件(如.o文件)。
  • 符号引用解决:这一阶段还会处理代码中的符号引用,确定所有引用的目标地址。

下一步就是汇编了,这有点小迷惑人,因为编译的结果是汇编文件,而汇编的结果是目标文件。

gcc中执行汇编步骤的选项是 -c ,示例命令如下。

gcc -c test.s -o test.o

输入的是 .s 文件,输出的是 .o文件。这一步就将我们的汇编转成机器码了,当我们再去查看的时候就不是我们能够看懂的了(虽然我估计大部分人连汇编都看不懂了(包括我))。

还有个需要说的,就是汇编这一步,可以直接从 .c到 .o,也就是可以跳过前两步直接到第三步。 

链接

最后一步链接,就可以生成可执行文件了。

  • 合并代码:链接器将所有的目标文件以及它们所需要的库文件合并,形成最终的可执行文件。
  • 解析外部引用:解决不同文件之间相互调用的函数或者变量地址解析问题。
  • 生成可执行文件:最终输出一个可执行的程序文件,该文件可以直接在操作系统上运行。

gcc中链接这一步骤不需要选项,也就是像下面这样。

gcc test.o -o test

直接输出没有后缀的可执行文件(可以让它的后缀为exe方便理解,但是在Linux中我们一般直接不要后缀)

那么我们就已经有了一个可执行文件了,应该怎么执行呢?

./test 

像上面这样一个点加个斜杠再加上可执行文件的名字就可以啦。

结果是下面这样的。

可能有小伙伴会说这个gcc也太麻烦了,我还是用IDE吧。

那其实我们要可执行文件的话可以不用按照这四个步骤一步步来,现实中我们不能一步登天,但是在gcc里可以,我们可以直接执行下面这个命令,直接从 .c 编译成可执行文件。

gcc test.c -o test

这样就简单很多了。

上面就是gcc最基本的用法了,懂得上面这几步之后,理论上去学个Makefile什么的问题不大。

不过我们可以再深入了解了解gcc,这个拥有着强大功能的工具不可能就做这么点事对吧。

指定头文件目录

假如我们现在写了一个含有功能函数的文件(或者是下载来的),那么我们在主函数要用对应的函数,那么就需要包含头文件对吧。

现在我在main.c文件的同级目录下专门建了个文件夹存放工具文件。并且我在main.c里包含了这些文件。像下面这样。

然后我们再编译就会发现gcc找不到我们的头文件。

这时候就要请出我们gcc指定头文件的选项 -I 了。

gcc -I ./my_tools test.c -o test

这样包含头文件就没问题了,但是又出了新的问题,那就是找不到函数定义了。

这是因为我们需要把被包含的文件一起放进来编译。

这样就没问题了,可是这样子写的话会非常麻烦,光是包含一个头文件就要加这一长串,万一我包含了很多呢?这就要请出我们的Makefile了(下一篇也可能是下n篇文章我们再说)。

总之我们先知道指定头文件目录的这个选项即可。

设置优化级

-O选项可以设置优化级,这边是大写的O,别和之前小写的o混一起了。

GCC编译器提供了多种优化级别,通过使用-O后跟一个数字(从0到3),可以指定希望GCC应用的优化等级。

  1. 优化级别0 (-O0)

    • 关闭所有编译优化。这是默认的编译设置,主要用于调试阶段,因为优化可能会改变程序的执行方式,从而影响调试的准确性。
  2. 优化级别1 (-O1)

    • 开启基本优化。这一级别的优化包括将常用值分配给寄存器、消除无用的代码等简单优化。这是在不影响调试的前提下提高程序性能的一个平衡选择。
  3. 优化级别2 (-O2)

    • 开启中级优化。除了包含-O1中的所有优化外,还包括了更复杂的优化如分支预测、循环展开、内联函数等。这可以显著提高程序的运行速度,但可能会增加编译时间和最终可执行文件的大小。
  4. 优化级别3 (-O3)

    • 开启高级优化。它包括-O2中的所有优化,并尝试进一步执行如函数内联扩展等更高级的优化技术。此级别适用于当程序性能是关键考虑因素时,但需要注意这可能会使编译时间变长,并且在某些情况下可能影响程序的稳定性或可预测性。
  5. 额外优化级别 (-Os)

    • -Os:专注于生成尽可能小的可执行文件大小。适用于嵌入式系统和那些对程序大小有严格要求的场景。

默认的优化级别是O0,一般情况下我们不动它的。

添加宏定义

这个会用的多一点。

-D后接我们要在编译时候注册的宏。

我现在修改一下我们之前的test.c文件。

然后我们直接编译,运行的结果是这样的。

当我们使用了-D选项,则是下面这样的效果。

通过这样的小例子,相信大家就对-D有了简单的认识了。

今天在这边就介绍到这边了,对于我们后续学习Makefile来说是足够的。

感觉不过瘾,想更深入了解gcc的小伙伴可以直接

man gcc

也可以去查官方文档。

GCC online documentation- GNU Projecticon-default.png?t=N7T8https://gcc.gnu.org/onlinedocs/

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

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

相关文章

IntelliJ IDEA 使用 Maven 时不加载本地私服的最新版本快照(snapshot)JAR 包

IntelliJ IDEA 使用 Maven 时不加载本地私服的最新版本快照&#xff08;snapshot&#xff09;JAR 包 目录 IntelliJ IDEA 使用 Maven 时不加载本地私服的最新版本快照&#xff08;snapshot&#xff09;JAR 包1. 检查 settings.xml2. IDEA Maven 配置3. 强制更新 Snapshot4. 使用…

解锁5G新营销:视频短信的优势与全方位推广策略

随着5G时代的全面来临&#xff0c;企业的数字化转型步伐日益加快&#xff0c;视频短信作为新兴的数字营销工具&#xff0c;正逐步展现出其巨大的潜力。视频短信群发以其独特的形式和内容&#xff0c;将图片、文字、视频、声音融为一体&#xff0c;为用户带来全新的直观感受&…

6月17号直播预告 | 认识XPCIE1032H控制卡以及单轴PSO视觉飞拍和精准输出知识分享

在智能装备领域&#xff0c;精度、效率和产能是关键的竞争力指标&#xff0c;大多数都面临备货排产要求高、需要调度协同生产和更高的加工精度等问题&#xff0c;特别是在3C电子、半导体设备、锂电光伏等高速高精制造领域。 运动控制系统的性能直接影响生产质量和效率&#xf…

Vue54-浏览器的本地存储webStorage

一、本地存储localStorage的作用 二、本地存储的代码实现 2-1、存储数据 注意&#xff1a; localStorage是window上的函数&#xff0c;所以&#xff0c;可以把window.localStorage直接写成localStorage&#xff08;直接调用&#xff01;&#xff09; 默认调了p.toString()方…

充电宝什么牌子耐用?2024年四大品牌推荐!这四款值得入!

在现代生活中&#xff0c;充电宝已经成为我们日常必备的数码配件之一。无论是旅行、出差还是日常通勤&#xff0c;拥有一款耐用且高效的充电宝&#xff0c;能够为我们的电子设备提供源源不断的电力支持。然而&#xff0c;市场上充电宝品牌众多&#xff0c;质量参差不齐&#xf…

Redis 7.x 系列【3】多种连接方式

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. Redis Cli3. 可视化管理工具3.1 Redis Insight3.2 RedisDesktopManager 4. …

AI图书推荐:用ChatGPT按需DIY定制来赚钱

《用ChatGPT按需DIY定制来赚钱》ChatGPT Print Money Method &#xff0c;作者是Cindy Donovan 。 下面是图书概要&#xff1a; ### 第一章&#xff1a;什么是按需印刷以及ChatGPT如何使其变得简单易行&#xff1f; 本章介绍了按需印刷的商业模式&#xff0c;即仅在收到订单时…

解析工业制氮机的应用特点

工业制氮机&#xff0c;作为现代工业生产中不可或缺的重要设备&#xff0c;以其独特的工作原理和广泛的应用领域&#xff0c;为众多行业提供了高效、便捷的氮气制取方案。本文将详细探讨工业制氮机的应用特点&#xff0c;以便更好地了解其在工业生产中的重要作用。 工业制氮机具…

「51媒体」媒体邀约如何高效沟通?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 企业在做活动会议时&#xff0c;往往希望对活动信息或者公司品牌进行一个报道和曝光&#xff0c;那么如何有效且高效的完成与媒体的沟通呢&#xff1f;今天胡老师就来分享下这方面的一些…

【Spring】1. Maven项目管理

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…

centos7 离线安装zip和unzip

解压的时候发现不能解压,报-bash: unzip: command not found 1、访问https://www.rpmfind.net/linux/rpm2html/search.php?query=zip&submit=Search+…&system=centos&arch=#/ 2、输入zip和centos搜索,选择el7下载 3、输入unzip和centos搜索,选择el7下载: 安…

【LLM之RAG】RAT论文阅读笔记

研究背景 近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;在各种自然语言推理任务上取得了显著进展&#xff0c;尤其是在结合大规模模型和复杂提示策略&#xff08;如链式思维提示&#xff08;CoT&#xff09;&#xff09;时。然而&#xff0c;LLMs 在推理的事实…

小程序简单版音乐播放器

小程序简单版音乐播放器 结构 先来看看页面结构 <!-- wxml --><!-- 标签页标题 --> <view class"tab"><view class"tab-item {{tab0?active:}}" bindtap"changeItem" data-item"0">音乐推荐</view><…

DAY5-力扣刷题

1.两两交换链表中的节点 24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换…

ElasticSearch + kibana:类型声明

当我们使用 kibana 创建索引时&#xff0c;如果不申明数据类型&#xff0c;默认字符串赋予 text类型&#xff0c;如下图所示 接下来我们继续创建多条数据如下&#xff1a; 下面我们来检索下&#xff1a; 通过以上两个案例我们发现&#xff0c;使用 match 模糊查询 li-3 明明…

亚马逊、速卖通等跨境平台测评自养号有哪些好处?

测评自养号顾名思义就是自己用国外真实环境养出来的买家账号&#xff0c;通过国外的手机号、邮箱、真实收货地址&#xff0c;设备环境、当地的住宅IP注册和养出来的买手号 很多卖家都了解过自养号&#xff0c;注册一个账号成本就几块钱&#xff0c;账号又可以长期使用&#xf…

【机器学习】图神经网络:深度解析图神经网络的基本构成和原理以及关键技术

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言一、图数据及其应用场景1.1 图数据的定义和特征1.2 常见的图数据结构1.2.1 社交网络1.2.2 知识图谱1.2.3 分子结构1.2.4 交通网络 1.3 图数据在不同领域的应用实例1.3.1 社交网络中的推荐系统1.3.2 知识图谱中的信息检索…

如何学习创建和使用 Java 归档(JAR)文件

1. 简介 JAR&#xff08;Java ARchive&#xff09;文件是一种用于打包多个Java类、资源文件和元数据的压缩文件格式。它在Java开发和发布过程中扮演着重要角色。通过使用JAR文件&#xff0c;开发者可以将应用程序的所有组件打包在一个文件中&#xff0c;方便分发和部署。 2. …

Visual Studio Code 配置教程,手把手教你如何配置

文章目录 引言1. 安装 VS Code1.1 下载和安装1.2 初次启动 2. 基本配置2.1 设置用户和工作区配置2.2 常用配置项 3. 安装和配置扩展插件3.1 安装扩展3.2 推荐扩展3.3 配置扩展 4. 主题和配色方案4.1 安装主题4.2 切换主题4.3 自定义配色方案 5. 版本控制集成5.1 配置 Git5.2 Gi…

COMSOL导入图片建模教程

研究背景 COMSOL Multiphysics作为多物理场仿真领域的高端软件&#xff0c;可允许用户通过建立数学模型来模拟和预测现实世界中的各种物理现象。将图片导入COMSOL软件进行建模&#xff0c;根植于现代科学研究和工程设计对高效、准确模拟技术日益增长的需求&#xff0c;它允许用…