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

C语言的编译过程详解

  • 当我们编译C程序时会发生什么?
  • 编译过程中的组件有哪些,编译执行过程是什么样的?
  • 什么是编译

    C语言的编译过程就是把我们可以理解的高级语言代码转换为计算机可以理解的机器代码的过程,其实就是一个翻译的过程。

                                                           源代码和可执行机器代码

程序编译是将源代码转换为可执行代码的过程,通常包括以下几个主要步骤:

  1. 预处理(Preprocessing): 在这个阶段,预处理器会处理源代码文件,执行一些预处理指令。常见的预处理指令包括#include(用于包含头文件)、#define(用于定义宏)、#ifdef#ifndef(用于条件编译)等。预处理器的输出通常是一个经过预处理的源代码文件。

  2. 编译(Compilation): 编译器接收预处理后的源代码并将其转换为汇编代码。汇编代码是一种低级的代码,与特定的计算机体系结构相关。编译器会执行语法分析、语义分析和代码生成等操作。如果在这个阶段发现语法错误或其他编译错误,编译过程会中止,并输出错误消息。

  3. 汇编(Assembly): 汇编器接收编译器生成的汇编代码,并将其转换为机器代码或可重定位目标代码。汇编过程将汇编指令转换为二进制形式,同时解析符号引用,生成可执行的机器代码或可链接的目标文件。

  4. 链接(Linking): 如果程序由多个源代码文件组成,编译后会生成多个目标文件。链接器接受这些目标文件以及所需的库文件,并将它们组合成一个可执行文件。链接过程涉及解析符号引用,将不同模块之间的引用关系解决,并生成最终的可执行文件。这也包括动态链接(在运行时加载共享库)或静态链接(在编译时将库链接到可执行文件)。

  5. 优化(Optimization)(可选): 一些编译器在生成目标代码之前会执行优化步骤,以提高程序的性能或减小可执行文件的大小。优化可以包括常量折叠、循环展开、内联函数、无用代码删除等操作。

  6. 生成可执行文件(Executable Generation): 最终的可执行文件包含了机器代码,它是计算机可以直接执行的二进制文件。这个文件可以通过操作系统加载到内存中,并执行。

总之,程序编译的过程包括预处理、编译、汇编、链接和可选的优化步骤,最终生成可执行文件。不同的编程语言和编译器可能在这个过程中有些许不同,但这个基本流程适用于大多数编程环境.

详细分析

C 语言的编译过程主要包括四个步骤:

  1. 预处理
  2. 编译
  3. 汇编
  4. 连接

下面这张图就是C程序编译的完整过程

接下我们看看编译过程不同阶段都在做什么。

1.预处理
编译过程的第一步预就是预处理,与处理结束后会产生一个后缀为(.i)的临时文件,这一步由预处理器完成。预处理器主要完成以下任务。

  • 删除所有的注释
  • 宏扩展
  • 文件包含

预处理器会在编译过程中删除所有注释,因为注释不属于程序代码,它们对程序的运行没有特别作用。

宏是使用 #define 指令定义的一些常量值或表达式。宏调用会导致宏扩展。预处理器创建一个中间文件,其中一些预先编写的汇编级指令替换定义的表达式或常量(基本上是匹配的标记)。为了区分原始指令和宏扩展产生的程序集指令,在每个宏展开语句中添加了一个“+”号。

文件包含
C语言中的文件包含是在预处理期间将另一个包含一些预写代码的文件添加到我们的C程序中。它是使用#include指令完成的。在预处理期间包含文件会导致在源代码中添加文件名的全部内容,从而替换#include<文件名>指令,从而创建新的中间文件。

2.编译
C 中的编译阶段使用内置编译器软件将 (.i) 临时文件转换为具有汇编级指令(低级代码)的汇编文件 (.s)。为了提高程序的性能,编译器将中间文件转换为程序集文件。
汇编代码是一种简单的英文语言,用于编写低级指令(在微控制器程序中,我们使用汇编语言)。整个程序代码由编译器软件一次性解析(语法分析),并通过终端窗口告诉我们源代码中存在的任何语法错误警告
下图显示了编译阶段如何工作的示例。

3.组装
使用汇编程序将程序集级代码(.s 文件)转换为机器可理解的代码(二进制/十六进制形式)。汇编程序是一个预先编写的程序,它将汇编代码转换为机器代码。它从程序集代码文件中获取基本指令,并将其转换为特定于计算机类型(称为目标代码)的二进制/十六进制代码。
生成的文件与程序集文件同名,在 DOS 中称为扩展名为 .obj 的对象文件,在 UNIX 操作系统中扩展名为 .o
下图显示了组装阶段如何工作的示例。程序集文件 hello.s 将转换为具有相同名称但扩展名不同的对象文件 hello.o。

4. 链接
链接是将库文件包含在我们的程序中的过程。库文件是一些预定义的文件,其中包含机器语言中的函数定义,这些文件的扩展名为.lib。一些未知语句写入我们的操作系统无法理解的对象 (.o/.obj) 文件中。你可以把它理解为一本书,里面有一些你不知道的单词,你会用字典来找到这些单词的含义。同样,我们使用库文件来为对象文件中的一些未知语句赋予意义。链接过程会生成一个可执行文件,其扩展名为 .exe 在 DOS 中为 .out,在 UNIX 操作系统中为 .out
下图显示了链接阶段如何工作的示例,我们有一个具有机器级代码的对象文件,它通过链接器传递,链接器将库文件与对象文件链接以生成可执行文件。

举例

接下来,我们通过一个例子详细看看C编译过程中涉及的所有步骤。第一步先写一个简单的C程序并保存为hello.c

// Simple Hello World program in C
#include<stdio.h>
int main()
{// printf() is a output function which prints// the passed string in the output consoleprintf("Hello World!");return 0;
}

接着我们执行编译命令对hello.c进行编译:

gcc -save-temps hello.c -o compilation

-save-temps 选项会保留所有编译过程中产生的中间文件,总共会生成四个文件。

  • hello.i 预处理器产生的文件
  • hello.s 编译器编译后产生的文件
  • hello.o 汇编程序翻译后的目标文件
  • hello.exe 可执行文件(Linux系统会产生hello.out文件)

首先,我们的C程序的预处理开始,注释从程序中删除,因为该程序中没有宏指令,因此宏扩展不会发生,我们还包含了一个stdio.h头文件,并且在预处理期间,标准输入/输出函数(如printf(),scanf()等)的声明被添加到我们的C程序中。

打开预处理阶段产生的hello.i 文件就可以看到类似下面这样的代码。

# 1 "hello.c"
# 1 ""
# 1 ""
# 1 "hello.c"# 1 "C:/Program Files (x86)/CodeBlocks/MinGW/include/stdio.h" 1 3
# 293 "C:/Program Files (x86)/CodeBlocks/MinGW/include/stdio.h" 3int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fprintf (FILE*, const char*, ...);int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) printf (const char*, ...);int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) sprintf (char*, const char*, ...);int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) scanf (const char*, ...);int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) sscanf (const char*, const char*, ...);...
...
...int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) putw (int, FILE*);
# 3 "hello.c" 2int main()
{printf("Hello World!");return 0;
}

从上面的代码中可以看到,预编译过后,所有的注释没有了,#include <stdio.h>也被它的头文件内容代替了。

接下来就是编译阶段,编译器接收到hello.i 文件将它转化为汇编代码hello.s文件。这过程中发生了以下几件事:

  • 编译器检查语法错误
  • 将源代码翻译中间代码,例如汇编代码
  • 对代码进行优化

编译结束后产生的hello.s 文件长这个样子:

.file	"hello.c".def	___main;	.scl	2;	.type	32;	.endef.section .rdata,"dr"
LC0:.ascii "Hello World!\0".text.globl	_main.def	_main;	.scl	2;	.type	32;	.endef
_main:
LFB12:.cfi_startprocpushl	%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl	%esp, %ebp.cfi_def_cfa_register 5andl	$-16, %espsubl	$16, %espcall	___mainmovl	$LC0, (%esp)call	_printfmovl	$0, %eaxleave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc
LFE12:.ident	"GCC: (MinGW.org GCC-6.3.0-1) 6.3.0".def	_printf;	.scl	2;	.type	32;	.endef

接下来,汇编程序把hello.s 文件转换为二进制代码,并在Windows环境中生成对象文件 hello.obj,在 Linux系统中生成 hello.o文件。

接着,链接器使用库文件将所需的定义添加到对象文件中,并在Windows环境中生成一个可执行文件 hello.exe,在 Linux操作系统中生成 hello.out文件。

  • 当我们运行 hello.exe/hello.out 时,我们会在屏幕上 输出 Hello World!。

程序流程图
让我们看一下C语言编译过程中程序的流程图:

结论

  • C中的编译过程也称为将人类可理解代码(C程序)转换为机器可理解代码(二进制代码)的过程。
  • C语言的编译过程包括四个步骤:预处理、编译、汇编和链接。
  • 预处理器执行删除注释、宏扩展、文件包含。这些命令在编译过程的第一步执行。
  • 编译器可以提高程序的性能,并将中间文件转换为汇编文件。
  • 汇编程序有助于将汇编文件转换为包含机器代码的对象文件。
  • 链接器用于将库文件与对象文件链接。这是编译中生成可执行文件的最后一步。

参考网址:

C程序的编译_c编译_。菀枯。的博客-CSDN博客

C语言的编译过程详解 - 知乎

相关文章:

C语言的编译过程详解

当我们编译C程序时会发生什么&#xff1f;编译过程中的组件有哪些&#xff0c;编译执行过程是什么样的? 什么是编译 C语言的编译过程就是把我们可以理解的高级语言代码转换为计算机可以理解的机器代码的过程&#xff0c;其实就是一个翻译的过程。 …...

无人机航测没信号?北斗卫星来解决

无人机航测是利用无人机进行地理信息的采集和处理的航测方式。相比传统的航测手段&#xff0c;无人机航测具备更高的灵活性、更低的成本和更广阔的适应性。无人机航测可以应用于土地测绘、农业植保、城市规划、自然资源调查等多个领域&#xff0c;极大地提高了测绘的效率和准确…...

Vue 03 数据绑定

Vue中有2种数据绑定的方式&#xff1a; 1.单向绑定(v-bind)&#xff1a; 数据只能从data流向页面。 2.双向绑定(v-model)&#xff1a; 数据不仅能从data流向页面&#xff0c;还可以从页面流向data。 备注&#xff1a; 1.双向绑定一般都应用在表单类元素上&#xff08;如&am…...

#循循渐进学51单片机#步进电机与蜂鸣器#not.8

1、能够理解清楚单片机IO口的结构。 2)t1相当于PnP三级管&#xff0c;t2相当于npn三极管 3&#xff09; 强推挽io具有较强的驱动能力&#xff0c;电流输出能力很强。 2、能够看懂上下拉电阻的电路应用&#xff0c;并且熟练使用上下拉电阻。 3、理解28BYJ-48减速步进电机的工作…...

计算存储是不是智算时代的杀手锏?

想象一下&#xff0c;在一个繁忙的数据中心里&#xff0c;有一家大型互联网公司叫做“数据中心的故事”。这家公司一直在使用传统的CPU架构来处理海量数据。但是随着数据量的不断增长&#xff0c;CPU架构遇到了很多问题和瓶颈&#xff0c;这让“数据中心的故事”感到非常苦恼。…...

西门子S7-1200F或1500F系列安全PLC的组态步骤和基础编程(二)

西门子S7-1200F或1500F系列安全PLC的组态步骤和基础编程(二) 上一次和大家分享了组态相关的重要内容,具体可以参考以下链接中的内容: 西门子S7-1200F或1500F系列安全PLC的组态步骤和基础编程(一) 本次继续和大家分享关于安全PLC基础编程的相关内容: 如下图所示,在左侧的…...

【Spring Boot】Spring Boot中的简单查询

前面介绍了在Spring Boot项目中集成JPA框架&#xff0c;实现数据的增、删、改、查等功能。Spring Data JPA的使用非常简单&#xff0c;只需继承JpaRepository即可实现完整的数据操作方法&#xff0c;无须任何数据访问层和SQL语句。JPA除了这些功能和优势之外&#xff0c;还有非…...

Transformer 01(自注意机制Self-attention)

一、Self-attention [台大李宏毅] 1.1 向量序列的输入 一个序列作为输入&#xff1a; 多个向量输入举例&#xff1a; 一个句子&#xff1a; 声音信号&#xff1a; 图&#xff1a; 1.2 输出 二、Sequence labeling 输入与输出一样多&#xff1a;Sequence labeling 窗口开的…...

交流共享,共筑智算底座丨九州未来受邀出席英特尔线下沙龙

随着AI技术的升级迭代、生成式AI模型智能化水平的持续提升&#xff0c;AIGC加速向多种场景渗透&#xff0c;AIGC迎来应用爆发期&#xff0c;有望实现且跨越更多领域的融合&#xff0c;形成新的应用场景和解决方案&#xff0c;持续推动数字技术的创新与应用&#xff0c;助力各行…...

【EI会议信息】第五届土木建筑与城市工程国际学术会议(ICCAUE 2023)

第五届土木建筑与城市工程国际学术会议&#xff08;ICCAUE 2023&#xff09; 2023 5th International Conference on Civil Architecture and Urban Engineering (ICCAUE 2023) 第五届土木建筑与城市工程国际学术会议&#xff08;ICCAUE 2023&#xff09;由天津大学主办&…...

上海亚商投顾:沪指震荡反弹 汽车产业链全天强势

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 大小指数昨日集体反弹&#xff0c;沪指3100点失而复得&#xff0c;创业板指一度涨超1.5%&#xff0c;随后涨幅…...

【Python深度学习】深度学习入门介绍

引言 深度学习是人工智能领域中最受关注和研究的子领域之一&#xff0c;它在计算机视觉、自然语言处理、语音识别、推荐系统等各个领域都有广泛的应用。本文将详细介绍深度学习的发展历史、不同类型、应用领域以及未来发展前景。 1、深度学习的发展历史 深度学习的起源可以追溯…...

【Linux系统编程】进程概念与基本创建

文章目录 1. 进程的概念2. 进程描述—PCB3. task_struct—PCB的一种4. task_ struct内容分类5. 查看进程 这篇文章我们来学习下一个概念——进程 1. 进程的概念 那什么是进程呢&#xff0c;我们该如何理解它呢&#xff1f; 如果我们打开电脑的任务管理&#xff1a; 我们看到这…...

webpack:详解CopyWebpackPlugin,复制的同时修改文件内容

摘要 CopyWebpackPlugin 是一个强大的 Webpack 插件&#xff0c;用于将文件从源目录复制到构建目录。在本文中&#xff0c;我们将探讨 CopyWebpackPlugin 的一些常用 API&#xff0c;并提供示例代码。 在构建 Web 应用程序时&#xff0c;通常需要将一些静态文件&#xff08;如…...

Twin-Builder—系统级多物理域数字孪生平台

Twin Builder是ANSYS公司系统仿真业务的核心产品&#xff0c;是一款跨学科多领域系统仿真软件和数字孪生平台。能够实现复杂系统的建模、仿真和验证&#xff0c;基于IIoT物联网平台对数字孪生体进行集成、部署与运行&#xff0c;在完成复杂系统功能、性能的验证和优化的同时&am…...

用selenium和xpath定位元素并获取属性值以及str字符型转json型

页面html如图所示&#xff1a; 要使用xpath定位这个div元素&#xff0c;并且获取其属性data-config的内容值。 from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Optionshost127.0.0.1 port10808 …...

基于Java的电影院管理系统设计与实现

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…...

Linux Static Key原理与应用

文章目录 背景1. static-key的使用方法1.1. static-key定义1.2 初始化1.3 条件判断1.4 修改判断条件 2、示例代码参考链接 背景 内核中有很多判断条件在正常情况下的结果都是固定的&#xff0c;除非极其罕见的场景才会改变&#xff0c;通常单个的这种判断的代价很低可以忽略&a…...

linux ssh 禁止指定用户通过ssh登录

Linux 禁止用户或 IP通过 SSH 登录 限制用户 SSH 登录 1.只允许指定用户进行登录&#xff08;白名单&#xff09;&#xff1a; 在 /etc/ssh/sshd_config 配置文件中设置 AllowUsers 选项&#xff0c;&#xff08;配置完成需要重启 SSHD 服务&#xff09;格式如下&#xff1a…...

快速学习Netty

Netty框架探索&#xff1a;助力高效网络编程 一、Netty是个啥&#xff1f;二、“Hello World”服务器端实现&#xff08;Server&#xff09;客户端实现&#xff08;Client&#xff09;思考&#x1f914; 三、Netty的核心组件EventLoopChannelChannelPipelineChannelHandlerByte…...

对类和对象的详细解析

目录 1.类的构成 2.this指针 3.C类里面的静态成员 3.1 类里面的静态成员函数 3.2 类里面的静态成员变量 静态成员变量的特点 共享性 存储位置 生命周期 访问权限 如何初始化&#xff1f; 构造函数 1.类的构成 public修饰的成员在类外可以直接被访问 private和protecte…...

matlab 间接平差法拟合二维圆

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。爬虫自重。 一、算法原理 圆的方程为: ( x - x 0 )...

pgzrun 拼图游戏制作过程详解(10)

10. 拼图游戏继续升级——多关卡拼图 初始化列表Photos用来储存拼图文件名&#xff0c;Photo_ID用来统计当下是第几张拼图&#xff0c;Squares储存当下拼图的24张小拼图的文件名&#xff0c;Gird储存当下窗口上显示的24个小拼图及坐标。 Photos["girl_","boy_…...

glog与pugi::xml使用方法

&#xff08;一&#xff09;glog的使用:google logging的简称&#xff1b; &#xff11;&#xff09;需要安装&#xff0c;网上一搜一大堆&#xff0c;不在赘述&#xff1b; &#xff12;&#xff09;在cmakelists.txt中&#xff0c;需要链接"-glog"&#xff0c;如&a…...

windows下MySQL服务不见,服务无法启动,服务闪退,提示“本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止”

文章目录 前情提示1.解决MySQL服务消失2.解决MySQL服务无法启动 前情提示 后台启动MySQL服务出现闪退 或 “本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止”&#xff0c;可以参考以下方法。 我的电脑上安装了双版本MySQL&#xff0c;这里…...

剑指offer(C++)-JZ67:把字符串转换成整数atoi(算法-模拟)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 写一个函数 StrToInt&#xff0c;实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。…...

嵌入式笔试面试刷题(day15)

文章目录 前言一、Linux中的主设备号和次设备号1.查看方法2.主设备号和次设备号的作用 二、软件IIC和硬件IIC的区别三、变量的声明和定义区别四、static在C和C中的区别五、串口总线空闲时候的电平状态总结 前言 本篇文章继续讲解嵌入式笔试面试刷题&#xff0c;希望大家坚持跟…...

【Docker】Dockerfile构建镜像

一、编写Dockerfile文件 编写镜像需要的运行环境&#xff08;Linux、java等&#xff09;&#xff0c; Dockerfile文件内容如下&#xff1a; # 使用官方的 Ubuntu 16.04 镜像作为基础镜像 FROM ubuntu:16.04# 更新包列表 RUN apt-get update# 安装所需的软件包 RUN apt-get ins…...

fota升级,可卸载apk也进行更新

首先如题目要求 可卸载apk是通过刷机或恢复出厂设置之后执行脚本安装的 然后fota升级后&#xff0c;在判断是否“是第一次刷机和恢复出厂设置”时候会返回false&#xff0c;就导致脚本没有执行。导致apk升级不成功 所以我们要完成这个就是&#xff0c;确定fota什么时候升级完…...

ASP.NET dotnet 3.5 实验室信息管理系统LIMS源码

技术架构&#xff1a;ASP.NET dotnet 3.5 LIMS作为一个信息管理系统&#xff0c;它有着和ERP、MIS之类管理软件的共性&#xff0c;如它是通过现代管理模式与计算机管理信息系统支持企业或单位合理、系统地管理经营与生产&#xff0c;最大限度地发挥现有设备、资源、人、技术的…...

做网站的诈骗8000块钱犯法吗/合肥网站优化方案

在一个目录下的搜索&#xff0c;即FindElem&#xff08;&#xff09;不分先后出现顺序。 (一) 先讲一下XML中的物殊字符&#xff0c;手动填写时注意一下。 字符 字符实体& &amp;或#38; &apos…...

外包网靠谱吗/sem与seo

本文通过开发一个JSP 编辑器插件的示例&#xff0c;介绍了 Eclipse 中设置 JSP 断点的方法&#xff0c;以及如何远程调试 JSP。作为基础知识&#xff0c;本文的前两部分描述了 JAVA Debug 和 JSR-45 的基本原理。环境要求: 本文的代码是在 Eclipse3.0.0&#xff0c;JDK1.4.2 和…...

做游戏视频网站/找广告商的平台

阿里云监控系统支持用户自定义监控类型&#xff0c;具有极强的监控扩展能力&#xff0c;支持用户自己编写监控插件实现自定义监控类型。编写完后将插件放到Agent安装目录下面的scripts目录下面&#xff0c;如果是linux服务器则是/usr/local/cms/scripts目录下面。 监控插件不管…...

电脑做网站空间/windows优化大师是系统软件吗

对于python列表里元素的操作主要分为以下几个方面&#xff1a; 1、向列表里面加元素&#xff1b; 向python列表里面添加元素主要有三种方法&#xff1a; &#xff08;1&#xff09;append&#xff08;&#xff09; append()对于列表的操作主要实现的是在特定的列表最后添加一个…...

wordpress搭建企业官网/网络营销百度百科

第三十二~三十三章&#xff1a;最小操作数&#xff0c;木块砌墙问题作者&#xff1a;July、caopengcs、红色标记。致谢&#xff1a;fuwutu、demo。时间&#xff1a;二零一三年八月十二日题记再过一两月&#xff0c;便又到了每年的九月十月校招高峰期&#xff0c;在此依次推荐&a…...

哪个购物网站最便宜/设计一个公司网站多少钱

周虎摘 要&#xff1a;JWT(JsonWebToken)认证作为一种服务器端无状态验证方式&#xff0c;在分布式开发中得到了广泛的应用。但是&#xff0c;由于token信息的本身特点&#xff0c;支持的有效时间是固定的&#xff0c;当在token有效时间内用户操作没有完成&#xff0c;操作就会…...