GCC编译过程:预处理->编译->汇编->链接
目录
引言
概括介绍
一、预处理
二、编译
三、汇编
四、链接
总结
引言
当使用集成开发环境(IDE)进行C语言编程时,点击"编译"按钮后,整个C程序从源代码到可执行文件的生成过程会自动完成。IDE会在后台为我们执行C语言的编译过程,将源代码转换为最终的可执行文件。虽然IDE隐藏了底层的细节,但理解编译过程对于程序员来说仍然是很有价值的。
概括介绍
gcc
和g++
都是GNU编译器套件(GNU Compiler Collection,简称GCC)的一部分,其中gcc
用于编译C语言代码,而g++
用于编译C++语言代码。它们的编译过程在大部分情况下是类似的,但根据输入文件的扩展名和一些默认选项的不同,它们会调用不同的编译器前端,即C前端或C++前端。
下面是gcc
和g++
的编译过程的概述
-
预处理(Preprocessing):首先,对源文件进行预处理。预处理器将处理源代码中的预处理指令,比如以
#
开头的指令,如#include
、#define
等,并展开宏定义。预处理后的代码会生成一个.i
文件,通常是在临时目录中。 -
编译(Compiling):接下来,编译器前端会将预处理后的源代码编译成汇编代码(
.s
文件)。此阶段会检查语法和语义错误,并进行优化,但不会生成可执行代码。 -
汇编(Assembling):汇编器(as)将汇编代码转换成机器代码,并生成目标文件(
.o
文件)。 -
链接(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文件)
二、编译
编译是预处理后代码的第二个阶段。编译器前端(例如
cc1
或cc1plus
)接收预处理后的代码,并将其转换成汇编代码。在编译阶段,编译器执行以下主要任务:
语法和语义检查:编译器检查代码是否符合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程序的可执行文件。
总结
生成可执行程序过程为成四个步骤:
- 由.c文件到.i文件,这个过程叫预处理。
- 由.i文件到.s文件,这个过程叫编译。
- 由.s文件到.o文件,这个过程叫汇编。
- 由.o文件到可执行文件,这个过程叫链接。
在集成开发环境中,点击"编译"按钮后,IDE会自动完成上述四个阶段,无需手动执行每个步骤。如果没有编译错误,最终的可执行文件将生成并可以在IDE中直接运行。
虽然IDE为我们提供了方便的编译工具,但了解C语言的编译过程仍然对于程序员来说是重要的,特别是在解决一些编译错误或进行优化时,理解底层过程可以帮助我们更好地理解和改进代码。
相关文章:

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

JVM笔记 —— 出现内存溢出错误时时如何排查
一、出现内存溢出的几种情况 内存溢出错误分为StackOverflowError和OutOfMemoryError,前者是栈中出现溢出,后者一般是堆或方法区出现溢出,简称OOM 1. 栈溢出 StackOverflowError 栈溢出一般都是因为没有正确的结束递归导致的,无…...
多级嵌套引入组件导致Vue提示子组件未注册问题
发生此问题的时候是页面解析的时报错的, 所以可以放在beforeCreate中执行注册组件这个时候是在页面运行时执行的,运行时编译就结束了 第一种:可以在父组件中动态注册组件 export default{beforeCreate(){//require是commonJS,commonJS导入ES…...
vue3+element-plus组件下拉列表,数组数据转成树形数据
引入组件 可以直接在项目中引入element-plus表格组件,如果需要变成下拉列表样式需要添加以下属性: row-key 必填 最好给数字或唯一属性 , 给每个节点设置id 不填的话 没有办法实现展开效果 load 这个是动态添加数据的 前提(开启…...
【kubernetes】调度约束
目录 调度约束 Pod 启动典型创建过程如下 调度过程 指定调度节点 查看详细事件(发现未经过 scheduler 调度分配) 获取标签帮助 需要获取 node 上的 NAME 名称 给对应的 node 设置标签分别为 ggls 和 gglm 查看标签 修改成 nodeSelector 调度方…...

【深度学习MOT】SMILEtrack SiMIlarity LEarning for Multiple Object Tracking,论文
论文:https://arxiv.org/abs/2211.08824 文章目录 AbstractIntroduction2. 相关工作2.1 基于检测的跟踪2.1.1 检测方法2.1.2 数据关联方法 2.2 基于注意力的跟踪 3. 方法3.1 架构概述3.2 用于重新识别的相似性学习模块(SLM) 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代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Spring AOP 切点表达式
参考博客: 参考博客...

打破传统直播,最新数字化升级3DVR全景直播
导语: 近年来,随着科技的不断创新和发展,传媒领域也正经历着一场前所未有的变革。在这个数字化时代,直播已经不再仅仅是在屏幕上看到一些人的视频,而是将观众带入一个真实世界的全新体验。其中,3DVR全景直…...
网络安全--利用awk分析Apache日志
一、溯源 你会溯源吗?怎么溯 拿到日志(ssh登录日志,Apache日志),通过日志溯到ip,对日志进行每天的拆分,第二通过awk日志分析工具对每天的日志进行拆分,分析某一个ip今天对我访问多…...

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

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

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

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

大数据分析案例-基于KMeans和DBSCAN算法对汽车行业客户进行聚类分群
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
Vue 3 中定义组件常用方法
在Vue 3 中有多种定义组件的方法。从选项到组合再到类 API,情况大不相同 1、方式一:Options API 这是在 Vue 中声明组件的最常见方式。从版本 1 开始可用,您很可能已经熟悉它。一切都在对象内声明,数据在幕后由 Vue 响应。它不是…...
Linux | curl命令调用接口时查看调用时长和详情
关注wx: CodingTechWork 引言 在服务器中通过curl命令调用接口时,我们经常需要分析一些时长。本文主要总结两种方式进行处理。 curl命令 使用time命令 time curl -k -u <username>:<password> https://127.0.0.1/xxxx -vvv 使用文本 编…...

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

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

2.3 物理层设备
在这个视频中,我们要学习工作在物理层的两种网络设备,分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间,需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质,假设A节点要给…...

CSS3相关知识点
CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...