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

GCC编译过程:预处理->编译->汇编->链接

目录

引言

 概括介绍

一、预处理

二、编译

三、汇编

四、链接

总结


引言

当使用集成开发环境(IDE)进行C语言编程时,点击"编译"按钮后,整个C程序从源代码到可执行文件的生成过程会自动完成。IDE会在后台为我们执行C语言的编译过程,将源代码转换为最终的可执行文件。虽然IDE隐藏了底层的细节,但理解编译过程对于程序员来说仍然是很有价值的。

 概括介绍

gccg++都是GNU编译器套件(GNU Compiler Collection,简称GCC)的一部分,其中gcc用于编译C语言代码,而g++用于编译C++语言代码。它们的编译过程在大部分情况下是类似的,但根据输入文件的扩展名和一些默认选项的不同,它们会调用不同的编译器前端,即C前端或C++前端。

下面是gccg++的编译过程的概述

  1. 预处理(Preprocessing):首先,对源文件进行预处理。预处理器将处理源代码中的预处理指令,比如以#开头的指令,如#include#define等,并展开宏定义。预处理后的代码会生成一个.i文件,通常是在临时目录中。

  2. 编译(Compiling):接下来,编译器前端会将预处理后的源代码编译成汇编代码(.s文件)。此阶段会检查语法和语义错误,并进行优化,但不会生成可执行代码。

  3. 汇编(Assembling):汇编器(as)将汇编代码转换成机器代码,并生成目标文件(.o文件)。

  4. 链接(Linking):最后,链接器(ld)将目标文件与所需的库文件链接在一起,生成最终的可执行文件。

下面让我们在Linux环境下简单示例C程序编译过程加深理解

代码示例(main.c):

#include<stdio.h>int main(){printf("Hello Linux\n");return 0;
}

一、预处理

预处理是编译过程的第一步,它处理以#开头的预处理指令,并展开宏定义。预处理器会执行以下主要任务:

  • 处理#include指令:将指定的头文件内容插入到源代码中。这样,可以在源文件中使用其他函数或变量的声明和定义。

  • 处理宏定义:将代码中定义的宏展开为对应的表达式或语句。例如,#define MAX_VALUE 100将会在源代码中把所有MAX_VALUE替换为100

  • 处理条件编译指令:如#ifdef#ifndef#if等,这些指令根据条件判断是否编译部分代码块。

预处理后的代码会生成一个.i文件,这是一个展开了所有宏和包含了所有头文件的中间文件。

语法示例

gcc -E main.c -o main.i

 命令中-E是让编译器在预处理之后就退出,不进行后续编译过程,-o是指定输出文件名。

使用该指令的结果是将stdio.h文件全部内容插入到main.c形成main.i文件。

可以看到预处理之后的main.i文件显然比main.c文件大得多。我们查看一下main.i文件,因为此时main.i依然是文本文件。

(使用head指令查看main.i文件)

二、编译

编译是预处理后代码的第二个阶段。编译器前端(例如cc1cc1plus)接收预处理后的代码,并将其转换成汇编代码。在编译阶段,编译器执行以下主要任务:

  • 语法和语义检查:编译器检查代码是否符合C/C++语法规则,并进行语义分析,以确保代码没有逻辑错误。

  • 生成中间表示:编译器将代码转换成中间表示形式,通常是一种低级的、与特定硬件无关的表示。

  • 优化:编译器可能对中间表示进行优化,以提高程序的执行效率和代码质量。

编译阶段不会生成可执行文件,而是将代码转换成汇编代码,通常保存为.s文件。

语法示例

gcc -S main.i -o main.s

命令中-S让编译器在编译之后停止,不进行后续编译过程,-o是指定输出文件名。

编译成汇编文件大小已经非常小了,相对于预处理之后的main.i文件小很多。

编译过程完成后,将生成程序的汇编代码test.s,这也是文本文件。我们查看一下。

 图中即为main.s中的汇编代码。

三、汇编

在汇编阶段,汇编器(as)接收编译生成的汇编代码,并将其转换为机器代码。汇编器的任务包括:

  • 将汇编代码转换为机器代码:将汇编代码中的汇编指令翻译成特定硬件架构能理解的机器指令。

  • 生成目标文件:生成一个或多个目标文件(.o文件),每个文件对应一个源文件或编译单元。

目标文件是机器代码的二进制表示形式,但它们还不是最终可执行的程序,因为某些符号引用可能仍然未解析。

语法示例

gcc -c main.s -o main.o

命令中-c选项,它告诉gcc只进行编译,不进行链接。因此,这个命令只会将汇编代码转换为目标文件,而不会生成可执行文件。-o是指定输出文件名。

目标文件test.o二进制表示的机器代码,可以作为链接的输入,用于生成最终的可执行文件。

四、链接

  • 链接器接收一个或多个目标文件,以及所需的库文件,并将它们合并成最终的可执行文件。
  • 链接器解析目标文件中的符号引用,找到对应的符号定义,并将符号重定位,以便正确地指向它们的定义。
  • 合并库文件,生成完整的可执行文件,其中包含所有的机器代码和解析后的符号。

语法示例

gcc main.o -o main

命令gcc main.o -o main是将目标文件(main.o)链接为可执行文件(main)的gcc命令。在这个命令中,我们没有使用-c选项,因此gcc会进行链接操作,生成最终的可执行文件。

当执行gcc main.o -o main命令时,gcc会将目标文件main.o与所需的库文件(如果有的话)一起进行链接,并生成最终的可执行文件main。这个可执行文件就是可以在Linux下运行的C程序。

 执行./main命令会运行名为main的可执行文件。这是我们之前用gcc命令生成的C程序的可执行文件。

总结

生成可执行程序过程为成四个步骤:

  1. 由.c文件到.i文件,这个过程叫预处理。
  2. 由.i文件到.s文件,这个过程叫编译。
  3. 由.s文件到.o文件,这个过程叫汇编。
  4. 由.o文件到可执行文件,这个过程叫链接。

在集成开发环境中,点击"编译"按钮后,IDE会自动完成上述四个阶段,无需手动执行每个步骤。如果没有编译错误,最终的可执行文件将生成并可以在IDE中直接运行。

虽然IDE为我们提供了方便的编译工具,但了解C语言的编译过程仍然对于程序员来说是重要的,特别是在解决一些编译错误或进行优化时,理解底层过程可以帮助我们更好地理解和改进代码。

相关文章:

GCC编译过程:预处理->编译->汇编->链接

目录 引言 概括介绍 一、预处理 二、编译 三、汇编 四、链接 总结 引言 当使用集成开发环境&#xff08;IDE&#xff09;进行C语言编程时&#xff0c;点击"编译"按钮后&#xff0c;整个C程序从源代码到可执行文件的生成过程会自动完成。IDE会在后台为我们执行C…...

JVM笔记 —— 出现内存溢出错误时时如何排查

一、出现内存溢出的几种情况 内存溢出错误分为StackOverflowError和OutOfMemoryError&#xff0c;前者是栈中出现溢出&#xff0c;后者一般是堆或方法区出现溢出&#xff0c;简称OOM 1. 栈溢出 StackOverflowError 栈溢出一般都是因为没有正确的结束递归导致的&#xff0c;无…...

多级嵌套引入组件导致Vue提示子组件未注册问题

发生此问题的时候是页面解析的时报错的&#xff0c; 所以可以放在beforeCreate中执行注册组件这个时候是在页面运行时执行的&#xff0c;运行时编译就结束了 第一种&#xff1a;可以在父组件中动态注册组件 export default{beforeCreate(){//require是commonJS,commonJS导入ES…...

vue3+element-plus组件下拉列表,数组数据转成树形数据

引入组件 可以直接在项目中引入element-plus表格组件&#xff0c;如果需要变成下拉列表样式需要添加以下属性&#xff1a; row-key 必填 最好给数字或唯一属性 &#xff0c; 给每个节点设置id 不填的话 没有办法实现展开效果 load 这个是动态添加数据的 前提&#xff08;开启…...

【kubernetes】调度约束

目录 调度约束 Pod 启动典型创建过程如下 调度过程 指定调度节点 查看详细事件&#xff08;发现未经过 scheduler 调度分配&#xff09; 获取标签帮助 需要获取 node 上的 NAME 名称 给对应的 node 设置标签分别为 ggls 和 gglm 查看标签 修改成 nodeSelector 调度方…...

【深度学习MOT】SMILEtrack SiMIlarity LEarning for Multiple Object Tracking,论文

论文&#xff1a;https://arxiv.org/abs/2211.08824 文章目录 AbstractIntroduction2. 相关工作2.1 基于检测的跟踪2.1.1 检测方法2.1.2 数据关联方法 2.2 基于注意力的跟踪 3. 方法3.1 架构概述3.2 用于重新识别的相似性学习模块&#xff08;SLM&#xff09; Experimental Res…...

jmeter通过BeanShell对接口参数进行MD5和HmacSHA256加密【杭州多测师_王sir】

一、在eclipse里面编写MD5加密算法 package com.Base64;import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;public class Md5Utils {public static String md5(String sourceStr) {String result "";try {MessageDigest md Mess…...

基于自适应曲线阈值和非局部稀疏正则化的压缩感知图像复原研究【自适应曲线阈值去除加性稳态白/有色高斯噪声】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

Spring AOP 切点表达式

参考博客&#xff1a; 参考博客...

打破传统直播,最新数字化升级3DVR全景直播

导语&#xff1a; 近年来&#xff0c;随着科技的不断创新和发展&#xff0c;传媒领域也正经历着一场前所未有的变革。在这个数字化时代&#xff0c;直播已经不再仅仅是在屏幕上看到一些人的视频&#xff0c;而是将观众带入一个真实世界的全新体验。其中&#xff0c;3DVR全景直…...

网络安全--利用awk分析Apache日志

一、溯源 你会溯源吗&#xff1f;怎么溯 拿到日志&#xff08;ssh登录日志&#xff0c;Apache日志&#xff09;&#xff0c;通过日志溯到ip&#xff0c;对日志进行每天的拆分&#xff0c;第二通过awk日志分析工具对每天的日志进行拆分&#xff0c;分析某一个ip今天对我访问多…...

计算机视觉一 —— 介绍与环境安装

傲不可长 欲不可纵 乐不可极 志不可满 一、介绍 研究理论和应用 - 研究如何使机器“看”的科学 - 让计算机具有人类视觉的所有功能 - 让计算机从图像中&#xff0c;提取有用的信息&#xff0c;并解释 - 重构人眼&#xff1b;重构视觉皮层&#xff1b;重构大脑剩余部分 计…...

如何看懂统一社会信用代码?

在查看企业信息的时候&#xff0c;我们通常第一时间查看的就是该企业的照面信息&#xff1a;企业名称&#xff0c;企业信用代码&#xff0c;企业法人等等。 其中统一社会信用代码就是给各个企业组织编号&#xff0c;是便于统一识别管理的一串代码&#xff0c;类似我们的身份证…...

计算机网络 运输层端口号,复用、分用

...

systrace: 系统级跟踪工具的解析

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、获取systrace文件3.1 通过python命令获取3.1.…...

关于青少年学习演讲与口才对未来的领导力的塑造的探析

标题&#xff1a;青少年学习演讲与口才对未来领导力的塑造&#xff1a;一项探析 摘要&#xff1a; 本论文旨在探讨青少年学习演讲与口才对未来领导力的塑造的重要性和影响。通过分析演讲和口才对青少年的益处&#xff0c;以及如何培养这些技能来促进领导力的发展&#xff0c;我…...

大数据分析案例-基于KMeans和DBSCAN算法对汽车行业客户进行聚类分群

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…...

Vue 3 中定义组件常用方法

在Vue 3 中有多种定义组件的方法。从选项到组合再到类 API&#xff0c;情况大不相同 1、方式一&#xff1a;Options API 这是在 Vue 中声明组件的最常见方式。从版本 1 开始可用&#xff0c;您很可能已经熟悉它。一切都在对象内声明&#xff0c;数据在幕后由 Vue 响应。它不是…...

Linux | curl命令调用接口时查看调用时长和详情

关注wx&#xff1a; CodingTechWork 引言 在服务器中通过curl命令调用接口时&#xff0c;我们经常需要分析一些时长。本文主要总结两种方式进行处理。 curl命令 使用time命令 time curl -k -u <username>:<password> https://127.0.0.1/xxxx -vvv 使用文本 编…...

用ngrok实现内网穿透,一行命令就搞定!

最近在写支付的东西&#xff0c;调试时候需要让支付平台能够回调本地接口来更新支付成功的状态。但由于开发机器没有公网IP&#xff0c;所以需要使用内网穿透来让支付平台能够成功访问到本地开发机器&#xff0c;这样才能更高效率的进行调试。 推荐内网穿透的文章已经很多很多…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...