C语言的编译过程详解

news2024/11/26 17:06:06
  • 当我们编译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 console
    printf("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" 3
 int __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" 2

int 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_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	andl	$-16, %esp
	subl	$16, %esp
	call	___main
	movl	$LC0, (%esp)
	call	_printf
	movl	$0, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.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语言的编译过程详解 - 知乎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1024781.html

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

相关文章

python-列表解析、字典解析、集合解析

前言&#xff1a; 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 列表解析 生成一个列表 nums [1, 3, 9] list_gen [num**2 for num in nums if x < 5] # [1, 9]代码描述&#xff1a; 表达式&#xff…

基于SpringBoot+Vue的餐饮管理系统设计与实现

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

亚马逊云科技 Amazon Lightsail :一种在云服务器上运行容器的简单方法

当向开发人员介绍亚马逊云科技云服务时&#xff0c;通常会花一点时间来介绍并演示 Amazon Lightsail 。它是迄今为止开始使用亚马逊云科技的最简单方法。使用它&#xff0c;您在几分钟内即可在自己的虚拟服务器上运行您的应用程序。而后增加了在 Amazon Lightsail 上部署基于容…

[echarts] 两侧堆叠柱状图

http://echarts.zhangmuchen.top/#/detail?cidxOQSXIOQiK const myData [福田区, 罗湖区, 南山区, 盐田区, 宝安区, 龙岗区, 坪山区, 龙华区, 光明区, 大鹏区]; // 全彩屏&#xff0c;双基色屏&#xff0c;简易屏&#xff0c;条形屏 const offLine [[20, 40, 60, 60, 10, 2…

C语言 coding style

头文件 The #define Guard #define的保护文件的唯一性&#xff0c;防止被多重包含 格式 : <PROJECT>_< FILE>_H_ PROJECT : XS FILE : MV_CTR 头文件的包含顺序 C System FilesOther LibrariesUser LibraryConditional include 作用域 局部变量 -变量定义时需要…

Vuex状态管理最佳实践

文章目录 单一状态树使用模块使用常量定义Mutation类型使用Actions处理异步操作使用Getters计算属性严格模式分模块管理Getter、Mutation和Action&#xff1a;注释和文档&#xff1a;Vue Devtools ✍创作者&#xff1a;全栈弄潮儿 &#x1f3e1; 个人主页&#xff1a; 全栈弄潮…

计算机视觉与深度学习-卷积神经网络-纹理表示卷积神经网络-纹理表示-[北邮鲁鹏]

目录标题 参考文章纹理定义纹理的分类规则纹理随机纹理 纹理的表示方法基于卷积核组思路什么卷积核组卷积核类型&#xff08;边缘、条形、点状&#xff09;卷积核尺度&#xff08;3~6个尺度&#xff09;卷积核的方向卷积核组的设计 表示步骤步骤一&#xff1a;设计卷积核组。步…

软件测试/测试开发丨利用ChatGPT自动生成测试用例思维导图

点此获取更多相关资料 简介 思维导图是一种用图形方式表示思维和概念之间关系的工具&#xff1a; 有些公司会使用思维导图编写测试用例&#xff0c;这样做的优点是&#xff1a; 1.可视化和结构化。 2.易于理解&#xff0c;提高效率。 而 ChatGPT 是无法直接生成 xmind 格式…

Git学习笔记10

代码更新方法&#xff1a; 蓝绿部署&#xff1a; 蓝绿部署&#xff0c;英文名&#xff1a;Blue Green Deployment&#xff0c;是一种可以保证系统在不间断提供服务的情况下上线代码的部署方式。 如何保证系统不间断提供服务呢&#xff1f; 蓝绿部署的模型中包含两套集群。 …

ElementPlus·表单验证

表单验证作用&#xff1a;省去一些错误的请求提交&#xff0c;节省后端接口压力。简单配置、自定义配置&#xff0c;最后进行统一校验工作。 如何校验 及 校验步骤&#xff1a; 简单配置 <script setup> // 表单对象 const form ref({对象: 值 })// 规则对象 const ru…

21. 概率与统计 - 数学期望、统计描述分布

文章目录 数学期望方差标准差协方差二项分布高斯分布中心极限定理泊松分布Hi, 你好。我是茶桁。 在上一节中,我们最后有谈到随机变量。在概率论几统计学中,描述一个随机变量的离散程度的有方差、标准差等等。那么在这节课中,我们就来好好看看这些概念。 不过在这之前呢,我…

【音视频】FLV封装格式

基本概念 文件头(Header)文件体(Body) flv文件头 主要是看signture和typeflags flv文件体 重点&#xff1a;Tag包数据 Tag结构详细说明 注意&#xff1a; 每个Tag的头字段DataSize只是该Tag下data部分的大小&#xff0c;不包括Tag的header部分的大小 音频 AudioTag Data 所在…

若依+lodop+jasperreports+ireport 设计打印票据格式(二)

若依lodopjasperreportsireport 设计打印票据格式&#xff08;二&#xff09; 使用Field绑定Java传入数据 设计页表页数和当前页号 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7091542bd5954845b8fcf39d71d4c9e4.png#pic_cente![在这里插入图片描述](https://img-bl…

[Vue] 绑定下拉菜单

写在前面 同学们&#xff0c;今天的天气很是不错&#xff0c;我们之前进行了复选框的绑定&#xff0c;这次来看看下拉菜单的绑定吧&#xff0c;因为要赶这个创作进度&#xff0c;真的只有再水一篇文章了。大家就当是饭后甜点看看就行。 苏子云 荷尽已无擎雨盖&#xff0c;菊残…

红海云荣膺「2023智享会人力资源技术供应商价值大奖」

9月19日&#xff0c;由中国高端人力资源会员组织智享会&#xff08;HREC&#xff09;主办的“2023人力资源技术供应商价值大奖”颁奖典礼隆重举行&#xff0c;红海云凭借卓越的技术实力与品牌口碑荣膺“2023 HCM系统-本地部署HR臻选供应商”。 智享会“价值大奖”系列评选被称…

基于STM32+华为云IOT设计的智能垃圾桶

一、项目介绍 在商业街、小吃街和景区等人流密集的场所&#xff0c;垃圾桶的及时清理对于提供良好的游客体验至关重要。然而&#xff0c;传统的垃圾桶清理方式通常是定时或定期进行&#xff0c;无法根据实际情况进行及时响应&#xff0c;导致垃圾桶溢满&#xff0c;影响环境卫…

钉钉stream机器人-实操详细教程

支持事件订阅、机器人收消息、卡片回调等功能 优点&#xff1a; 配置简单&#xff0c;不依赖也不需要暴露公网IP&#xff0c;无需向公网开放端口 github官方链接&#xff1a;GitHub - open-dingtalk/dingtalk-stream-sdk-python: Python SDK for DingTalk Stream Mode API, Co…

低噪声 256 细分微步进电机驱动MS35774/MS35774A(汽车应用级别)

MS35774/MS35774A 是一款高精度、低噪声的两相步进 电机驱动芯片&#xff0c;芯片内置功率 MOSFET&#xff0c;长时间工作的平均电 流可以达到 1.4A&#xff0c;峰值电流 2A。芯片集成了过温保护、欠压 保护、过流保护、短地保护、短电源保护功能。 主要特点 ◼ 2 相步进电机…

excel subtotal 函数(分类汇总)

函数说明 返回列表中的分类汇总。 语法 SUBTOTAL(function_num,ref1,[ref2],...) SUBTOTAL 函数语法具有以下参数&#xff1a; Function_num 必需。 数字 1-11 或 101-111&#xff0c;用于指定要为分类汇总使用的函数。 如果使用 1-11&#xff0c;将包括手动隐藏的行&…

glTF模型骨骼动画

推荐&#xff1a;使用 NSDT场景编辑器快速搭建3D应用场景 本文详细演示了风车动画的制作过程&#xff1a; 当然&#xff0c;这非常容易硬编码&#xff08;有两个对象&#xff0c;一个静态的&#xff0c;一个旋转的&#xff09;。但是&#xff0c;我计划稍后添加更多动画&#…