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

news2025/1/31 16:05:18
  • 前提: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.out
    
    gcc 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.coloradmin.cn/o/1329593.html

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

相关文章

python+django教学质量评价系统o8x1z

本基于web的在线教学质量评价系统的设计与实现有管理员,教师,督导,学生一共四个角色。管理员功能有个人中心,学生管理,教师管理,督导管理,学生评价管理,课程信息管理,学生…

万界星空开源MES/注塑MES/开源注塑MES/免费MES/MES源码

一、系统概述: 万界星空科技免费MES、开源MES、商业开源MES、市面上最好的开源MES、MES源代码、适合二开的开源MES、好看的数据大屏、功能齐全开源mes. 1.万界星空开源MES制造执行系统的Java开源版本。 开源mes系统包括系统管理,车间基础数据管理&…

.net core webapi 自定义异常过滤器

1.定义统一返回格式 namespace webapi;/// <summary> /// 统一数据响应格式 /// </summary> public class Results<T> {/// <summary>/// 自定义的响应码&#xff0c;可以和http响应码一致&#xff0c;也可以不一致/// </summary>public int Co…

《Python》面试常问:深拷贝、浅拷贝、赋值之间的关系(附可变与不可变)【用图文讲清楚!】

背景 想必大家面试或者平时学习经常遇到问python的深拷贝、浅拷贝和赋值之间的区别了吧&#xff1f;看网上的文章很多写的比较抽象&#xff0c;小白接收的难度有点大&#xff0c;于是乎也想自己整个文章出来供参考 可变与不可变 讲深拷贝和浅拷贝之前想讲讲什么是可变数据类型…

【基础知识】大数据组件HBase简述

HBase是一个开源的、面向列&#xff08;Column-Oriented&#xff09;、适合存储海量非结构化数据或半结构化数据的、具备高可靠性、高性能、可灵活扩展伸缩的、支持实时数据读写的分布式存储系统。 只是面向列&#xff0c;不是列式存储 mysql vs hbase vs clickhouse HMaster …

R语言贝叶斯网络模型、INLA下的贝叶斯回归、R语言现代贝叶斯统计学方法、R语言混合效应(多水平/层次/嵌套)模型

目录 ㈠ 基于R语言的贝叶斯网络模型的实践技术应用 ㈡ R语言贝叶斯方法在生态环境领域中的高阶技术应用 ㈢ 基于R语言贝叶斯进阶:INLA下的贝叶斯回归、生存分析、随机游走、广义可加模型、极端数据的贝叶斯分析 ㈣ 基于R语言的现代贝叶斯统计学方法&#xff08;贝叶斯参数估…

【Android】存储读取权限管理理解和api 调研报告

背景 工作和学习需要了解android 权限管理和 对应的api 调用逻辑。 学习 内部路径 不用权限 /data/data/应用包名 相关API Context 类 getCacheDir 缓存路径 getCodeCacheDir 示意路径 getFilesDir 内部文件 文件路径 fileList &#xff08;files 下的所有文件名&…

Go 代码检查工具 golangci-lint

一、介绍 golangci-lint 是一个代码检查工具的集合&#xff0c;聚集了多种 Go 代码检查工具&#xff0c;如 golint、go vet 等。 优点&#xff1a; 运行速度快可以集成到 vscode、goland 等开发工具中包含了非常多种代码检查器可以集成到 CI 中这是包含的代码检查器列表&…

旧衣回收小程序搭建有什么优势?

今年以来&#xff0c;旧衣回收行业分外火热&#xff0c;不断有创业者进入到市场中&#xff0c;其中不乏有年轻人&#xff0c;足以可见行业的火爆。 我国是人口大国&#xff0c;每个人闲置的衣物加在一起的数量难以计算&#xff0c;旧衣回收行业具有巨大的发展空间。 此外&…

【JS】事件循环机制

一、JS单线程、异步、同步概念 众所周知&#xff0c;JS是单线程&#xff08;如果一个线程删DOM&#xff0c;一个线程增DOM&#xff0c;浏览器傻逼了&#xff5e;所以只能单着了&#xff09;&#xff0c;虽然有webworker酱紫的多线程出现&#xff0c;但也是在主线程的控制下。we…

基于博弈树的开源五子棋AI教程[4 静态棋盘评估]

引子 静态棋盘的评估是棋力的一个很重要的体现&#xff0c;一个优秀的基于博弈树搜索的AI往往有上千行工作量&#xff0c;本文没有做深入讨论&#xff0c;仅仅写了个引子用来抛砖引玉。 评估一般从两个角度入手&#xff0c;一个是子力&#xff0c;另一个是局势。 1 评估维度 …

【视觉实践】使用Mediapipe进行目标检测:杯子检测和椅子检测实践

目录 1 Mediapipe 2 Solutions 3 安装mediapipe 4 实践 1 Mediapipe Mediapipe是google的一个开源项目,可以提供开源的、跨平台的常用机器学习(machine learning,ML)方案。MediaPipe是一个用于构建机器学习管道</

Python之Django项目的功能配置

1.创建Django项目 进入项目管理目录&#xff0c;比如&#xff1a;D盘 执行命令&#xff1a;diango-admin startproject demo1 创建项目 如果提示diango命令不存在&#xff0c;搜索diango-admin程序的位置&#xff0c;然后加入到环境变量path中。 进入项目&#xff0c;cd demo…

层次分析法

层次分析法主要用于解决评价类问题(例如选择哪种方案最好&#xff0c;哪位运动员或者员工表现的更优秀) 先用一道引出层次分析法的例题&#xff1a;小明同学高考填完志愿后&#xff0c;小明想出去旅游。在查阅了网上的攻略后&#xff0c;他初步选择了苏杭、北戴河和桂林三地之一…

[node]Node.js 模块系统

[node]模块系统 Node.js中的模块系统模块的使用模块的导入模块的导出导出多个值导出默认值导出可传参的函数 文件查找策略从文件模块缓存中加载从原生模块加载从文件加载 Node.js中的模块系统 为了让Node.js的文件可以相互调用&#xff0c;Node.js提供了一个简单的模块系统。 …

Web组态可视化编辑器-by组态

演示地址&#xff1a; http://www.by-lot.com http://www.byzt.net web组态可视化编辑器&#xff1a;引领未来可视化编辑的新潮流 随着网络的普及和快速发展&#xff0c;web组态可视化编辑器应运而生&#xff0c;为人们在网络世界中创建和编辑内容提供了更加便捷的操作方式。这…

步兵 cocos2dx 加密和混淆

文章目录 摘要引言正文代码加密具体步骤代码加密具体步骤测试和配置阶段IPA 重签名操作步骤 总结参考资料 摘要 本篇博客介绍了针对 iOS 应用中的 Lua 代码进行加密和混淆的相关技术。通过对 Lua 代码进行加密处理&#xff0c;可以确保应用代码的安全性&#xff0c;同时提高性…

H266/VVC帧内预测编码

预测编码技术 预测编码&#xff08;Prediction Coding&#xff09;是指利用已编码的一个或多个样本值&#xff0c;根据某种模型或方法&#xff0c;对当前的样本值进行预测&#xff0c;并对样本真实值和预测值之间的差值进行编码。 视频中的每个像素看成一个信源符号&#xff…

基于iOS平台的车牌识别表情识别项目

基于iOS平台的车牌识别&&表情识别项目 简介 ​ 该项目客户端搭载于iOS平台&#xff0c;服务端搭载于阿里云服务器&#xff0c;主要功能是通过拍照或选取相册图片来进行车牌的识别以及人脸表情识别。本文便是对项目整体流程设计思路和具体实现做一个详细介绍。 整体实…

LSTM和GRU vs 普通的循环神经网络RNN

1、考虑下列三种情况下&#xff0c;对比一下普通RNN的表现和LSTM和GRU表现&#xff1a; &#xff08;1&#xff09;早期观测值对预测未来观测者具有非常重要的意义。 考虑一个极端情况&#xff0c;其中第一个观测值包含一个校验和&#xff0c; 目标是在序列的末尾辨别校验和是…