【Linux/gcc】C/C++——编译过程

  • 前提:WSL2(Ubuntu)、gcc编译器。
  • gcc安装命令:
    • sudo apt-get install gcc
  •  查看gcc版本:

目录

1、编译过程

1.1、预处理

1.2、编译与汇编

1.3、链接

2、gcc实验

2.1、预处理

2.2、编译

2.3、汇编

2.4、链接


1、编译过程

  • 对于c/c++编程,从源代码文件变成可执行文件,大致需要以下几步:
    • 预处理 (Pre-Processing)
      • 预处理器处理#include、#define等内容,把头文件复制到源文件中等。
    • 编译 (Compiling)
      • 得到以汇编语言写的,可读的文件。
    • 汇编 (Assembling)
      • 得到二进制格式,不可读的文件。
      • 编译和汇编主要是分析源代码中的内容,然后转换为目标文件。
    • 链接 (Linking)
      • 静态库和动态库的处理体现在链接过程中,链接器把目标文件和库一起打包变成可执行文件。
    • 【注】c/c++的编译过程和java、python等语言不同。

1.1、预处理

  • 预处理主要的工作包括:
    • 文件包含,通常包括系统的头文件和自定义的头文件。
    • 宏定义的处理,例如,#define PI 3.14,替换相应的内容。
    • 条件编译,例如,#ifdef、#ifndef、#else、#elif、#endif等,可以结合宏的使用实现部分编译,防止头文件重复包含等。
    • 特殊控制,例如#pragma命令,#error命令等。
    • 添加行号和文件名标识,清理注释内容等。
  • 预处理指令不属于C/C++语言的标准语法,一定意义上也可以说预处理扩展了C/C++,因此预处理的具体语法和实现,与编译器以及平台相关。

1.2、编译与汇编

  • 这是编译过程的核心部分,主要步骤有:
    • 词法分析
    • 语法分析
    • 语义分析
    • 代码优化
  • 到这一步为止,我们从源文件 (和头文件) 得到了目标文件,通常每一个源文件都应该对应产生一个目标文件。下一阶段是链接,会把目标文件和库文件结合在一起,得到可执行文件 (二进制程序)。
  • 为了得到正确的目标文件,这个环节重点检查:语法的正确函数以及变量的声明和使用的正确。
    • 【注】这一阶段,只要能在头文件中找到正确的声明即可,并不负责检查外部函数和变量是否被正确实现和定义,可以接收空头支票。
  • 与之不同的是,下一阶段的链接器并不对源文件进行操作,它面对的就是目标文件和库文件,这个环节需要重点检查的是跨文件的符号 (外部函数和外部变量) 是否都被实现,并且把它们合并到一起 (它需要检查,编译时开出的空头支票是否都被兑现),如果出现了符号未定义或者符号重复定义,就会报链接错误。

1.3、链接

  • 链接就是将目标文件和库文件打包、组装成可执行文件的过程。这里库文件就是早已完成的,可重复使用的成熟组件,而刚刚实现的源文件已经被处理为目标文件,等待着被一起打包组装。
  • 链接环节要解决的问题是,怎么让各个不同的模块可以一起工作。有的文件中使用的符号在另一个文件中定义,有的函数具体在另一个文件中实现。链接需要让它们互相认识,重定位,确定符号的对应关系,统一进行地址分配等。
    • 例如,hello.c源文件使用了printf这个函数,通过stdio.h这个头文件中的函数声明可以明白它的用法,但是它的具体实现其实是在动态库libc.so.6,链接的时候需要引用这个库文件。
  • 根据指定的链接库函数的方式不同,链接过程可分为静态链接和动态链接两种。选择静态链接时,相当于把库中需要用到的部分直接拷贝过来;选择动态链接时,相当于仅仅登记一下库的基本信息,等执行的时候再去查找和加载动态库。
    • 静态链接:从库中将需要用到的部分内容直接拷贝到最终的可执行程序中。
      • 优点:可执行文件一旦生成,就与这个库没有联系,自己可以独立运行。
      • 缺点:可执行文件体积较大,有很多重复的空间占用;如果更新升级库中的功能,则所有用到这个库的可执行文件必须重新编译。
    • 动态链接:编译时暂时记录一下动态库的基本信息,但不会拷贝其中的具体内容,等到运行时再去寻找需要的动态库,将其加载到内存中一起执行。
      • 优点:可执行文件体积较小,可以节约空间,多个程序可以共同利用同一个基础的动态库;可以灵活升级动态库的功能,如果保证二进制层面的兼容性,那么用到它的相关程序不需要重新编译。
      • 缺点:可执行文件执行时仍然需要这个动态库,执行时很可能遇到动态库找不到,动态库版本不兼容等问题。
  • 由于两种链接方式对应的文件格式不同,一个具体的库只能被动态链接或只能被静态链接。通常的库可以提供静态库版本和动态库版本,可以灵活选择。
  • gcc如果同时找到了一个库的静态库版本和动态库版本,默认情况下会使用动态库,进行动态链接。 

2、gcc实验

  • 创建c文件:
    • mkdir project01  # 创建存放c文件的文件夹
      cd project01  # 进入文件夹
      vim hello.c  # 创建并编写c文件
  • 编写hello.c: 
    • 按 i,进入插入模式,编辑文件。
    • 编辑完毕后按回退键,输入 :wq,保存文件。

2.1、预处理

  • 对于gcc来说,它会调用一个叫cpp的预处理工具,全称为C Pre-Processor (C 预处理器),是一个与C编译器独立的小程序,注意不是C Plus Plus。
  • gcc使用-E选项可以让编译过程在预处理步骤完成之后停止。
    • gcc -E hello.c -o hello.i
  • 【注】必须指明输出到文件hello.i,否则会把预处理结果直接输出到终端,建议的文件后缀为 .i。
  • 查看hello.i文件。
    • 得到的hello.i文件内容很长,仍然是可读的。文件前面的绝大部分都是头文件中的,原本的hello.c的内容在最后几行​​​​​​​。

2.2、编译

  • 这是整个编译过程的核心步骤,gcc调用的处理程序一般是cc。
  • gcc使用-S选项可以让编译过程在编译步骤完成之后停止。
    • gcc -S hello.c -o hello.s
      # 不加-o可以默认生成同名.s 汇编文件hello.s
      # 加-o选项则可以自定义输出文件名gcc -S hello.i -o hello.s
      # 对.c或者.i文件都可以执行上述命令,效果一样
  • 查看hello.s文件,即汇编语言文件。

2.3、汇编

  • gcc在这一环节调用的工具通常是as。
  • gcc使用-c选项可以让编译过程在编译步骤完成之后停止。
    • gcc -c hello.c -o hello.o
      # 使用-c选项会让gcc在第三步汇编之后就暂停
      # 不使用-o选项会默认生成同名的.o目标文件gcc -c hello.i -o hello.o
      gcc -c hello.s -o hello.o
      # 同样可以从.i .s中间文件出发,效果也是一样的
  • 得到的是二进制格式的目标文件。

2.4、链接

  • 链接过程是程序构建过程的最后一步,通常gcc调用ld来完成。
  • 链接指的是把目标文件组合起来,变成可执行文件。由于当前例子只有单个文件,没有库文件,只会自动链接系统的一些库,暂时不需要关注这些细节。
  • gcc hello.o -o hello
    # 从目标文件得到可执行文件gcc hello.o
    # 省略-o选项相当于 -o a.outgcc hello.c
    gcc hello.i
    gcc hello.s
    # 同样可以从.c .i .s文件出发,效果也一样
  • 【注】gcc可以编译c++文件,但是不能自动链接c++程序使用的库,所以一般使用g++编译c++程序。 
    • 但是也可以使用gcc手动链接c++库,具体看:用gcc编译C++文件_gcc可以编译c++吗-CSDN博客
  •  生成的hello为可执行文件,直接运行即可。
    • ./hello
    •  

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

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

相关文章

XSKY星辰天合星海架构荣获 IT168 “2023 年度技术卓越奖”

近日,"2023 年度技术卓越奖"获奖名单公布,XSKY 星辰天合的星海架构(XSEA,极速全共享架构)获得行业 CIO/CTO 大咖、技术专家及 IT 媒体三方认可,成功入选! “技术卓越奖”评选由国内著…

2. 结构型模式 - 桥接模式

亦称: Bridge 意图 桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用 问题 抽象? 实现? 听上去挺吓人? 让我们慢慢来&#x…

uniapp怎么动态渲染导航栏的title?

直接在接口请求里面写入以下: 自己要什么参数就写什么参数 本人仅供参考: this.name res.data.data[i].name; console.log(名字, res.data.data[i].name); uni.setNavigationBarTitle({title: this.name}) 效果:

【Proteus仿真】【Arduino单片机】智能垃圾桶设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器,使用报警模块、LCD1602液晶模块、按键模块、人体红外传感器、HCSR04超声波、有害气体传感器、SG90舵机等。 主要功能: 系统运行后&am…

14、Qt使用Eigen3

一、下载Eigen Eigen 二、创建项目 创建一个"Qt Widget Application"项目,基类选择“QMainWindow“,把Eigen拷贝到项目中 三、更改代码 在.pro中添加 INCLUDEPATH $$PWD\Eigen 在界面上添加一个pushButton,并转到槽&#xff0…

111基于matlab的粒子滤波进行锂离子电池的循环寿命预测

基于matlab的粒子滤波进行锂离子电池的循环寿命预测,输出实验、粒子滤波及自然预测数据结果。程序已调通,可直接运行。 111matlab锂离子电池寿命预测 (xiaohongshu.com)

JavaEE:CAS详解

一.什么是CAS CAS: 全称 Compare and swap ,字面意思 :” 比较并交换 “ ,一个 CAS 涉及到以下操作: 我们假设内存中的原数据V,旧的预期值A,需要修改的新值B。 我们来进行操作: 1. 比较 V 和 A 是否相等。…

蓝桥杯第二场小白入门赛(1~5)(对不起,我线段树太菜了)

1.模拟 2.贪心 3.二分 4.数论 5.数论 6.线段树&#xff08;线段树还是练少了...&#xff09; 1. 蓝桥小课堂-平方和 直接模拟&#xff0c;注意数据范围 #include <bits/stdc.h> using namespace std; #define LL long long #define pb push_back #define x first …

低代码开发:数字化转型的引擎

引言 在当今数字化时代&#xff0c;组织面临着不断变化的市场需求和技术挑战。数字化转型已成为维持竞争力的关键&#xff0c;而低代码开发正在崭露头角&#xff0c;成为加速创新和数字化转型的有力工具。本文将深入探讨低代码开发的核心概念、优势和应用&#xff0c;以揭示它…

亚马逊圣诞关键词怎么选?亚马逊圣诞节促销活动有哪些?——站斧浏览器

亚马逊圣诞关键词怎么选&#xff1f; 以下是在亚马逊圣诞期间利用长尾关键词的一些建议&#xff1a; 圣诞主题关键词&#xff1a;随着节日的临近&#xff0c;与圣诞相关的关键词搜索热度将急剧上升。在产品标题、描述、关键词等位置使用与圣诞节相关的关键词&#xff0c;比如…

【数据结构一】初始Java集合框架(前置知识)

Java中的数据结构 Java语言在设计之初有一个非常重要的理念便是&#xff1a;write once&#xff0c;run anywhere&#xff01;所以Java中的数据结构是已经被设计者封装好的了&#xff0c;我们只需要实例化出想使用的对象&#xff0c;便可以操作相应的数据结构了&#xff0c;本篇…

【CentOS 7.9 分区】挂载硬盘为LVM操作实例

LVM与标准分区有何区别&#xff0c;如何选择 目录 1 小系统使用LVM的益处&#xff1a;2 大系统使用LVM的益处&#xff1a;3 优点&#xff1a;CentOS 7.9 挂载硬盘为LVM操作实例查看硬盘情况格式化硬盘创建PV创建VG创建LV创建文件系统并挂载自动挂载添加&#xff1a;注意用空格间…

pip 常用指令 pip list 命令用法介绍

&#x1f4d1;pip 常用命令归类整理 pip list 是一个用于列出已安装的 Python 包的命令。这个命令会显示出所有已安装的包&#xff0c;以及它们的版本号。 pip list 命令有以下参数 -o, --outdated&#xff1a;列出所有过时的包&#xff0c;即有新版本可用的包。-u, --uptod…

3D 纹理贴图基础知识

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 介绍 纹理贴图是创建模型时离不开的最后一块拼图。同样&#xff0c;…

综合评价---DEA数据包络分析

数据包络分析(Data Envelopment Analysis&#xff0c;DEA)&#xff0c;1978年由 Charnes、Cooper和Rhodes创建的一种绩效评价技术(performance technique) 。采用多投入、多产出数据对多个决策单元(Decision Making Unit) 的相对效率进行评价因DEA的诸多优势&#xff0c;被广泛…

【数据结构之顺序表】

数据结构学习笔记---002 数据结构之顺序表1、介绍线性表1.1、什么是线性表? 2、什么是顺序表?2.1、概念及结构2.2、顺序表的分类 3、顺序表接口的实现3.1、顺序表动态存储结构的Seqlist.h3.1.1、定义顺序表的动态存储结构3.1.2、声明顺序表各个接口的函数 3.2、顺序表动态存储…

b2b订货系统成本是多少

批发贸易企业都上b2b订货系统&#xff0c;b2b订货系统成本究竟是多少&#xff0c;今天我们来算一算&#xff0c;尤其是最后一个大家可能会忽略。 一是b2b订货系统模板的功能费用&#xff0c;这部分一般各大厂家是明码标价&#xff0c;比如易订货12800元/年&#xff0c;核货宝首…

深入理解 Rust 中的容器类型及其应用

Rust 作为一种系统编程语言&#xff0c;提供了丰富的容器类型来处理各种数据结构和算法。这些容器类型不仅支持基本的数据存储和访问&#xff0c;还提供了高效的内存管理和安全性保障。本文将详细介绍 Rust 中的几种主要容器类型&#xff0c;包括它们的用法、特点和适用场景&am…

【IDEA】try-catch自动生成中修改catch的内容

编辑器 --> 文件和代码模板 --> 代码 --> Catch Statement Body

【雷达原理】雷达测速原理及实现方法

一、雷达测速原理 1.1 多普勒频率 当目标和雷达之间存在相对运动时&#xff0c;若雷达发射信号的工作频率为&#xff0c;则接收信号的频率为&#xff0c;其中为多普勒频率。将这种由于目标相对于辐射源运动而导致回波信号的频率发生变化的现象称为多普勒效应。 如图1-1所示&a…