为什么我们编写的C语言要进行编译?什么是编译?编译时发生了什么?
机器无法理解我们编写的C语言,而编译就是将面向人类的高级语言转换成为面向机器的机器语言的过程,图1是GCC编译器进行编译的过程,编译时主要分为了4个阶段,每个阶段的具体作用将在接下来进行介绍。
注:预处理中的cpp不是 c plus plus,而是c pre-process
命令:gcc -E hello.c -o hello.i
编译过程的第一步预就是预处理,预处理结束后会产生一个后缀为(.i)的临时文件,这一步由预处理器完成。预处理器主要完成以下任务。
#include :在系统指定路径下寻找stdio.h;
#include "stdio.h" :在当前路径下寻找stdio.h 如果找不到则在系统指定路径下寻找stdio.h。
根据不同情况编译不同代码、产生不同目标文件的机制,称为条件编译。条件编译是预处理程序的功能,不是编译器的功能;
这些操作都是在预处理阶段完成的,多余的代码以及所有的宏都不会参与编译,不仅保证了代码的正确性,还减小了编译后文件的体积;
条件编译主要处理内容为:#if,#ifdef,#ifndef, #if defined(AAA), #if defined AAA。
将宏定义的常量或函数进行替换。
命令:gcc -S hello.c -o hello.s
C 中的编译阶段使用内置编译器软件将 (.i) 临时文件转换为具有汇编级指令(低级代码)的汇编文件 (.s)。为了提高程序的性能,编译器将中间文件转换为程序集文件;
汇编代码是一种简单的英文语言,用于编写低级指令(在微控制器程序中,我们使用汇编语言)。整个程序代码由编译器软件一次性解析(语法分析),并通过终端窗口告诉我们源代码中存在的任何语法错误或警告。
命令:gcc -c hello.c -o hello.o。
使用汇编程序将程序集级代码(.s 文件)转换为机器可理解的代码(二进制/十六进制形式)。汇编程序是一个预先编写的程序,它将汇编代码转换为机器代码。它从程序集代码文件中获取基本指令,并将其转换为特定于计算机类型(称为目标代码)的二进制/十六进制代码;
生成的文件与程序集文件同名,在 DOS 中称为扩展名为 .obj 的对象文件,在 UNIX 操作系统中扩展名为 .o;
如图2显示了组装阶段如何工作的示例。程序集文件 hello.s 将转换为具有相同名称但扩展名不同的对象文件 hello.o。
图2
命令:gcc hello.c -o hello
链接是将库文件包含在我们的程序中的过程。库文件是一些预定义的文件,其中包含机器语言中的函数定义,这些文件的扩展名为.lib。一些未知语句写入我们的操作系统无法理解的对象 (.o/.obj) 文件中。你可以把它理解为一本书,里面有一些你不知道的单词,你会用字典来找到这些单词的含义。同样,我们使用库文件来为对象文件中的一些未知语句赋予意义。链接过程会生成一个可执行文件,其扩展名为 .exe 在 DOS 中为 .out,在 UNIX 操作系统中为 .out;
如上图2,显示了链接阶段如何工作的示例,我们有一个具有机器级代码的对象文件,它通过链接器传递,链接器将库文件与对象文件链接以生成可执行文件。
全部0条评论
快来发表一下你的评论吧 !