gcc的编译过程

article/2025/10/2 17:32:44

目录

一、gcc的编译过程

1.预处理

2.编译

3.汇编

4.连接


一、gcc的编译过程

        平时使用gcc,我们新手小白似乎只会使用它编译生成./a.out。

gcc hello.c

或者就是给生成的程序一个别名。

gcc hello.c -o hello

但是gcc还有很多的用处,而且了解gcc的编译过程对我们编译代码时也会提供很多帮助。

gcc编译过程有四大步骤:预处理、编译、汇编、链接

1.预处理

预处理是读取c源程序,对其中的伪指令(以#开头的指令,也就是宏)和特殊符号进行“替代”处理;经过此处理,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,仍然是C文件,但内容有所不同。

预处理的过程主要处理包括以下过程:
        ·将所有的#define删除,并且展开所有的宏定义
        ·处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等
        ·处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
        ·删除所有注释 “//”和”/* */”.
        ·添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
        ·保留所有的#pragma编译器指令,因为编译器需要使用它们

下面我们将一端简单的C代码做示例。

/* --------普通的c代码----------*/
#include<stdio.h>
#define COUNTE 5
int main(int argc,char ** argv)
{for(int i=0;i<=COUNTE;i++){printf("hello world!");}return 0;
}

然后经过预处理:gcc -E hello.c -o hello.i   //-E只对其预处理,或者可以cpp hello.c > hello.i

 其注释被删除,且宏也被替代之后删除,如上图所示。

2.编译

        编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。

        gcc  -S hello.i -o hello.s(-S将.i文件生成.s汇编文件)如下图

         不同的编译器交叉编译同一个hello.i文件生成的汇编文件也不相同,这也是C语言可移植性的一种体现。

3.汇编

        汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。 目标文件由段组成。通常一个目标文件中至少有两个段:
        ·代码段(文本段):该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般不可写;
        ·数据段:主要存放程序中要用到的各种常量、全局变量、静态的数据。一般数据段都是可读,可写,可执行的;

gcc -c hello.s -o hello.o    //-c汇编文件,不链接

4.连接

         汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。 链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体,也就是可执行程序。 根据开发人员指定的库函数的链接方式的不同,链接处理可分为两种:
        1. 静态链接
        2. 动态链接

        对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。

        gcc hello.o -o hello -static//静态链接编译

       gcc hello.o -o hello //动态链接编译

         可见两种编译生成的可执行文件大小的差距,静态连接编译将静态库包含在了生成的可执行文件中,增加了其独立性,但是也使其文件大小更大。


http://chatgpt.dhexx.cn/article/Q00I58Sx.shtml

相关文章

多线程和异步的区别

首先说明&#xff0c;这里介绍的区别可能有些浅显&#xff0c;内部更深层的原理&#xff0c;说实在的&#xff0c;我现在有点理解不了&#xff0c;大家可以参考以下两个地方&#xff0c;主要是以C#为主要语言&#xff1a; c#关于异步编程&#xff1f; C# 彻底搞懂async/await …

单线程与多线程使用场景

多线程使用时机 出现CPU资源浪费&#xff08;CPU空转&#xff09;的时候才适用多线程&#xff0c;每个核心在同一时刻只能处理一个线程&#xff0c;而逻辑处理器则是通过CPU的并发来模拟出的核心 单线程与多线程使用情况 适用单线程的情况 CPU全力执行&#xff0c;没有产生…

多线程与并发 - 进程和线程的区别

进程和线程的由来&#xff1a; 进程是资源分配的最小单位&#xff0c;线程是CPU调度的最小单位 所有与进程相关的资源&#xff0c;都被记录在PCB中进程是抢占处理机的调度单位&#xff1b;线程属于某个进程&#xff0c;共享其资源线程只由堆栈寄存器、程序计数器和线程控制表&…

多线程并发和并行的区别

背景 对于java开发从业人员来说&#xff0c;并发编程是绕不开的话题&#xff0c;juc并发包下提供了一系列多线程场景解决方案。  随着jdk1.8的普及&#xff0c;多线程处理问题&#xff0c;除了使用使用线程池(ExecutorService)&#xff0c;很多人选择了parallelStream() 并行流…

多线程与单线程理解

多线程与单线程理解 进程与线程的关系 进程是计算机程序执行一次过程的接班单位&#xff0c;即正在执行的程序&#xff08;QQ&#xff09;&#xff0c;一个应用程序可以包含多个进程&#xff08;QQ的不同页面信息&#xff09; 线程是进程的基本单元&#xff0c;一个进程至少包…

线程和进程的区别与联系以及单线程多进程与单进程多线程的区别

线程和进程 概念 进程&#xff08;process&#xff09;&#xff1a;是指具有已一定功能的独立程序&#xff0c;是系统资源分配的基本单位&#xff0c;在内存中有其完备的数据空间和代码空间&#xff0c;拥有完整的虚拟空间地址。一个进程所拥有的数据和变量只属于它自己。 线…

单线程与多线程的区别?

什么是进程&#xff1f; 当一个程序开始运行时&#xff0c;它就是一个进程&#xff0c;进程包括运行中的程序和程序所使用到的内存和系统资源。 而一个进程又是由多个线程所组成的。 什么是线程&#xff1f; 线程是程序中的一个执行流&#xff0c;每个线程都有自己的专有寄存器…

单线程与多线程

目录 多线程的创建 方式一&#xff1a;继承Thread类 方式二&#xff1a;实现Runnablel接口 方式三&#xff1a;JDK5.0新增Callable接口 Thread的常用方法 线程安全 线程同步 线程通信 线程池【重点】 定时器 补充知识&#xff1a;并发、并行 生命周期 什么是线程&…

什么是单线程和多线程,单线程与多线程的区别

什么是进程&#xff1f; 当一个程序开始运行时&#xff0c;它就是一个进程&#xff0c;进程包括运行中的程序和程序所使用到的内存和系统资源。 而一个进程又是由多个线程所组成的。 什么是线程&#xff1f; 线程是程序中的一个执行流&#xff0c;每个线程都有自己的专有寄存器…

理解单线程和多线程的区别

单线程和多线程 首先我们都知道线程是隶属于进程的,单线程就是程序中只有一个线程,多线程就是程序中有多个线程.通过连个例子理解多线程和单线程. (一)单线程 创建包:package com.ffyc.javathread; 创建类:public class Sample { } package com.ffyc.javathread; public c…

ubuntu卸载已安装软件

1.查看已安装软件列表 dpkg -l dpkg -l | grep baidu # 软件包查询筛选# 另外&#xff0c;软件安装也使用dpkg命令 sudo dpkg -i xxxx.deb2.卸载指定软件包 sudo apt-get purge baidunetdisk # 卸载指定软件 sudo apt-get autoremove # 清理不需要的文件 sudo apt-get autoc…

Ubuntu20.04 卸载软件

Ubuntu20.04卸载软件相当的简单&#xff0c; 一 用命令行卸载 sudo apt-get remove --purge 软件名 这样不仅可以卸载掉软件&#xff0c;而且可以清理配置 二 在图形界面卸载软件 首先打开设置 打开应用程序 在其中找到你要卸载的软件 然后点击右上角的 在软件中打开 然后…

Linux bash卸载软件,Ubuntu卸载软件的4种方法

前言 本文重点介绍Ubuntu卸载软件的4种方法。他们分别是图形化界面的synaptic、自动解决依赖关系的apt-get,处理依赖关系更强大的aptitude,还有安装本地deb包的dpkg。 方法一: Ubuntu使用synaptic图形化界面管理软件 oucanrong@zcwyou:~$ sudo apt-get install synaptic -y 以…

Ubuntu卸载软件方式

1、终端输入&#xff1a; dpkg --list 显示出电脑上所有的软件包 左边就是软件名字&#xff0c;中间是版本名 2、在终端上输入命令sudo apt --purge remove 包名 例如我要卸载smartgit 即可

Ubuntu卸载软件

1、利用"软件中心"卸载 在Ubuntu收藏栏中打开软件中心&#xff0c;在已安装的软件中找到要卸载的软件&#xff0c;点击“移除”按钮即可。 提示&#xff1a;需要输入用户密码。 2、在终端中卸载 2.1、找到软件 有些软件在“软件中心”中是找不到的。还是需要用终端…

Ubuntu卸载软件相关命令

查看安装的软件 dpkg -l 查看软件版本 dpkg -l | grep xxx # xxx为软件名称&#xff0c;例如 virtualbox 查看包是否安装 dpkg-query -l *package-name* 例如 virtualbox dpkg -s package-name 例如 virtualbox 列出你系统中安装的所有包&#xff0c;同样可以通过grep…

Ubuntu命令卸载软件

1.打开一个终端&#xff0c;输入dpkg --list ,按下Enter键&#xff0c;终端输出以下内容&#xff0c;显示的是你电脑上安装的所有软件。 2.在终端中找到你需要卸载的软件的名称&#xff0c;列表是按照首字母排序的。 3.在终端上输入命令sudo apt-get --purge remove 包名…

A星算法优化(二)权重系数

本文接上一篇&#xff1a;A星算法优化&#xff08;一&#xff09;启发函数 B站详解视频&#xff1a;https://www.bilibili.com/video/BV1EF411W7Rw?spm_id_from333.999.0.0 将从以下5个点进行改进&#xff1a; 1、启发函数——曼哈顿距离等 2、权重系数——动态加权等 3、搜索…

A_star算法

A*算法 A* 搜索算法&#xff0c;即A star search algorithm&#xff0c;简称A* 算法。 是一种在图形平面上对于多个节点的路径求出最低通过成本的算法。是对图的遍历和最佳优先搜索算法&#xff0c;也是对BFS的改进。其思想在于为每个状态建立启发函数&#xff0c;用启发函数制…

A star算法

A star算法介绍 我们在解空间搜索问题的可行解或者最优解时常用宽度优先搜索(BFS)或者深度优先搜索(DFS)&#xff0c;但是有时候会扩展出很多无用节点&#xff0c;搜索时间较长&#xff0c;而A*算法则是选择当前估计成本最低的节点进行扩展&#xff0c;图示如下: g(n)为从起始…