国外扁平化网站设计欣赏,二手建筑铝模板哪里有卖,网站开发者morz,邮箱官网登录入口当我们编译C程序时会发生什么#xff1f;编译过程中的组件有哪些#xff0c;编译执行过程是什么样的? 什么是编译 C语言的编译过程就是把我们可以理解的高级语言代码转换为计算机可以理解的机器代码的过程#xff0c;其实就是一个翻译的过程。 …当我们编译C程序时会发生什么编译过程中的组件有哪些编译执行过程是什么样的? 什么是编译 C语言的编译过程就是把我们可以理解的高级语言代码转换为计算机可以理解的机器代码的过程其实就是一个翻译的过程。 源代码和可执行机器代码
程序编译是将源代码转换为可执行代码的过程通常包括以下几个主要步骤 预处理Preprocessing 在这个阶段预处理器会处理源代码文件执行一些预处理指令。常见的预处理指令包括#include用于包含头文件、#define用于定义宏、#ifdef 和 #ifndef用于条件编译等。预处理器的输出通常是一个经过预处理的源代码文件。 编译Compilation 编译器接收预处理后的源代码并将其转换为汇编代码。汇编代码是一种低级的代码与特定的计算机体系结构相关。编译器会执行语法分析、语义分析和代码生成等操作。如果在这个阶段发现语法错误或其他编译错误编译过程会中止并输出错误消息。 汇编Assembly 汇编器接收编译器生成的汇编代码并将其转换为机器代码或可重定位目标代码。汇编过程将汇编指令转换为二进制形式同时解析符号引用生成可执行的机器代码或可链接的目标文件。 链接Linking 如果程序由多个源代码文件组成编译后会生成多个目标文件。链接器接受这些目标文件以及所需的库文件并将它们组合成一个可执行文件。链接过程涉及解析符号引用将不同模块之间的引用关系解决并生成最终的可执行文件。这也包括动态链接在运行时加载共享库或静态链接在编译时将库链接到可执行文件。 优化Optimization可选 一些编译器在生成目标代码之前会执行优化步骤以提高程序的性能或减小可执行文件的大小。优化可以包括常量折叠、循环展开、内联函数、无用代码删除等操作。 生成可执行文件Executable Generation 最终的可执行文件包含了机器代码它是计算机可以直接执行的二进制文件。这个文件可以通过操作系统加载到内存中并执行。
总之程序编译的过程包括预处理、编译、汇编、链接和可选的优化步骤最终生成可执行文件。不同的编程语言和编译器可能在这个过程中有些许不同但这个基本流程适用于大多数编程环境. 详细分析
C 语言的编译过程主要包括四个步骤
预处理编译汇编连接 下面这张图就是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
#includestdio.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头文件并且在预处理期间标准输入/输出函数如printfscanf等的声明被添加到我们的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语言的编译过程详解 - 知乎