1.预处理(Pre-Processing)
2.编译(Compiling)
3.汇编(Assembling)
4.链接(Linking)
1.预处理(Pre-Processing)
读取c源程序,对其中的伪指令(以#开头的指令)和 预定义符号进行处理
伪指令主要包括以下四个方面
(1)宏定义指令:
如#define,#undef。
(2)条件编译指令:
如#ifdef,#ifndef,#else,#elif,#endif,等等。
这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉
(3)头文件包含指令:
如#include "FileName"或者#include <stdio.h>等。
使用< >引用的头文件是告诉编译器要到系统指定的目录下去寻找
而使用 " " 引用的头文件是告诉编译器先在默认目录下查找, 如果默认目录下找不到则再到系统目录下查找
一般情况下, 你自己写的头文件用 " ",编译器自带的头文件用< >
这样方便区别头文件的类型
如果全部用 " "也是可以的, 只不过不符合规范结构而已。
(4)预定义符号,预编译程序可以识别一些预定义符号。
C语言编译器的预定义符号:
__LINE__ 当前(源代码文件)行号 [整数]
__FILE__ 当前正在编译的文件的文件名 [字符串]
__DATE__ 当前日期,以“月月 日日 年年年年”的形式给出 [字符串]
__TIME__ 当前时间,以“HH:mm:ss”的格式给出 [字符串]
__STDC__ 如果编译器符合ANSI C标准,该宏为1,否则为0
__STDC_HOSTED__ 如果实现了所有C标准库,该宏为1,否则为0
__STDC_VERSION__ 被定义为199901L(不同编译器可能不一样,比如gcc里就没有这个预定义符号)
注:这些预定义符号的首尾为两个下划线,如果是两个单词,中间以一个下划线连接。
如果在源代码中使用了这些符号,它们会在预处理时被转换(使用gcc编译器的 -E 选项可以看到替换后的值)
C 标准里还在每个函数内预定义了一个标志符: __func__
它被定义为 static const char __func__[]="function-name";
即不能在程序内对__func__赋值,也不能改变它所指向的字符串(函数名),否则报编译错误
注:__func__是个标志符,它在预处理阶段不被替换,所以使用gcc -E 是看不到任何效果的。
预编译程序对于在源程序中出现的预定义符号将用合适的值进行替换。
预编译程序所完成的基本上是对源程序的“替代”工作。
经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同。下一步,此输出文件将作为编译程序的输出而被翻译成为机器指令。
2.编译(Compiling)
预编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
3.汇编(Assembling)
汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。
汇编阶段就是把编译阶段生成的".s"文件转成目标文件。
4.链接(Linking)
由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);
在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。
根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
(1)静态链接
在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。
(2)动态链接
在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。
经过上述4个过程,C源程序就最终被转换成可执行文件了。
gcc一些编译选项:
-std=<标准> 指定输入源文件遵循的标准
--sysroot=<目录> 将 <目录> 作为头文件和库文件的根目录
-B <目录> 将 <目录> 添加到编译器的搜索路径中
-E 仅作预处理,不进行编译、汇编和链接
-S 编译到汇编语言,不进行汇编和链接
-c 编译、汇编到目标代码,不进行链接
-o <文件> 输出到 <文件>
相关推荐
本资源“ROS的C++程序编译流程图.zip_ROS”包含了一个关于在ROS环境中编译C++程序的详细流程图,这对于理解ROS项目构建至关重要。以下是ROS C++程序编译的主要步骤: 1. **创建工作空间(Workspace)** 在ROS中,...
程序的基本流程如图: 1.预处理 预处理相当于根据预处理指令组装新的C/C++程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所...
测试使用的源码
Android 编译流程 Makefile 流程详解 Android 编译流程是 Android 系统开发的关键步骤之一,Makefile 是 Android 编译流程的核心组件。本文将详细介绍 Android 编译流程 Makefile 流程,并对其进行详细解释。 一、...
### PB程序反编译流程详解 #### 一、概述 PB(PowerBuilder)是一种用于开发企业级应用程序的软件开发工具,广泛应用于企业信息化建设中。当开发者需要对PB程序进行维护或更新时,通常需要通过反编译过程来获取源...
GCC编译流程:从源代码到可执行程序——浅析编译原理 GCC编译流程是从源代码到可执行程序的整个过程,可以分为四个阶段:预处理、编译、汇编和链接。下面将对这些阶段进行详细介绍: 1. 预处理阶段: 在预处理...
1. **驱动程序编译流程** - 首先,开发者需要编写好驱动程序代码,通常以`.c`文件的形式保存。 - 然后,将驱动程序文件放置在内核源码树的对应目录下,本例中是`drivers/char`目录。 - 接下来,需要对内核配置...
《Linux强弱符号的定义与区别》—— 程序的基本编译流程
### Android编译流程详解——Makefile流程 #### 一、引言 对于任何软件系统而言,深入了解其构建机制是至关重要的。特别是在复杂的操作系统如Android中,掌握编译流程能够帮助开发者更好地理解系统的内部结构和...
本文档详细介绍了MTK程序的编译流程,旨在帮助开发者理解和解决编译过程中遇到的问题,同时为优化编译过程提供指导。 MTK的编译过程主要在Windows命令行环境下进行,通过Makefile文件调用预处理脚本或C程序,将资源...
安卓编译流程是一个复杂而精细的过程,涉及到多个关键步骤和组件。本文将深入解析这一流程,帮助理解Android系统的构建机制。 首先,Android编译流程始于`Makefile`,这是一个核心控制文件,它调用`build/core/main...
### 使用dotnet生成DLL文件及编译流程 #### 一、使用dotnet生成DLL文件 在.NET Core或.NET 5及以上版本中,我们可以通过`dotnet`命令来创建和管理项目,包括生成DLL文件。以下步骤详细介绍如何通过`dotnet`工具在...
### 四、编译流程 1. **编写C源代码**:在PN中打开并编辑源代码文件(如`main.c`)。 2. **创建或修改Makefile**:根据项目需求,在文本编辑器中创建或修改`makefile`,指定芯片型号、时钟频率和其他编译选项。 3. ...
易语言流程控制编译原理源码,流程控制编译原理,是否汉字,读字符,是否运算符,是否逻辑运算符,指针回溯,跳过空格,跳过注释,代码块,取程序返回值,外部接口_代码块执行,外部接口_表达式计算,表达式计算,逻辑判断,文本到...
MTK(MediaTek)程序编译是一个复杂的过程,主要涉及在Windows环境下利用特定的工具链构建和打包手机软件。本文将详细介绍MTK编译环境的搭建、编译流程、常用的编译命令以及如何处理编译过程中遇到的问题。 首先,...
Visio C#程序编译软件是一款专为C#开发者设计的工具,主要用于辅助在Microsoft Visio环境中进行C#代码的开发、编译和调试。Visio是一款强大的图表绘制和流程图设计软件,而通过C#编程,我们可以进一步扩展其功能,...
此外,MTK还可能使用特定的构建系统,如MStarBuilder或者PDK,这些工具提供了自动化构建和管理编译流程的功能。 在编译过程中可能会遇到各种问题,如语法错误、链接错误、依赖冲突等。解决这些问题需要对C/C++编程...
### ASP.NET 页面编译流程详解 #### 一、概述 ASP.NET 是一种广泛使用的服务器端技术,用于构建动态网页和应用程序。它基于.NET框架或.NET Core,并提供了丰富的类库来帮助开发者快速创建功能强大的Web应用。ASP...