一、程序编译原理

  • 程序编译一般分为四个步骤,最后生成一个可执行的文件:


第一步(预处理):​在程序运行(main函数执行)之前,​修改源码​,主要处理代码中的#include头文件和#define宏定义代码(将程序运行时用到的#include头文件中的代码和#define宏定义的代码进行替换),最后生成一个.i文件(.i文件里面是替换代码之后的代码文件)​第二步(编译):​此阶段会检查代码的规范性、是否有语法错误等。在检查无误后,把.i代码文件进行编译,然后生成一个汇编语言.s文件(.s文件里面都是汇编语言)。此处只进行编译生成汇编代码,而不真正的进行汇编​第三步(汇编):​此阶段把​.s文件翻译成二进制机器指令.o文件​。生成的.o文件是二进制文件(直接用文本工具打开看到的将是乱码,我们需要反汇编工具如GDB的帮助才能读懂它),Windows下为.obj文件​第四步(链接):​此阶段会链接所有的函数、全局变量,将所有的.o文件链接成一个​可执行文件​(例如hello.c文件调用了printf函数,printf函数存在一个名为printf.o的文件中,而我们必须把printf.o合并到hello.o中​​。不过有时.o文件太多,链接会很不方便,所以我们会给.o文件进行打包生成静/动态库文件(Windows下为.lib和.dll文件,Linux下为.a和.so文件)

Linux(程序设计):01---程序编译原理(预处理、编译、汇编、链接)_预处理

  • 注意事项:

  • ​在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但仍可以生成Object File。但是链接时,链接器会在所有的Object File中找寻函数的实现,如果找不到,那到就会报链接错误码
  • ​一个.c文件只生成一个.i和.s和.o文件,链接时是将所有的.o文件一起链接
  • ​.h文件不直接参与源码编译,.cpp/.c等参与源码编译
  • ​承上,因为.h文件不参与源码编译,所以在.h文件中不要写带内存的代码

二、各种后缀名文件的意义


  • .c:C语言源代码文件
  • .h:是程序所包含的头文件
  • .i :预处理过的C源代码文件
  • .s:是汇编语言源代码文件
  • .o:是汇编之后的目标文件
  • .S:是经过预编译的汇编语言源代码文件

三、演示案例

  • 将一个hello.c文件进行预处理、编译、汇编、链接


第一步:预处理

gcc  -E -o  hello.i  hello.c

  • .i文件内容为:将.c里面用到的#include和宏定义的代码替换之后的代码文件

Linux(程序设计):01---程序编译原理(预处理、编译、汇编、链接)_程序编译原理_02



第二步:编译

gcc  -S  -o  hello.s  hello.i

  • .s里面是汇编语言

Linux(程序设计):01---程序编译原理(预处理、编译、汇编、链接)_源码编译_03



第三步:汇编

  • 编译生成一个二进制文件

gcc  -c  -o  hello.o  hello.s


第四步:链接

  • 链接生成一个可执行文件

gcc  -o  hello  hello.o


第五步:

  • 执行生成的hello可执行文件,打印出内容

​./hello​

Linux(程序设计):01---程序编译原理(预处理、编译、汇编、链接)_汇编语言_04

Linux(程序设计):01---程序编译原理(预处理、编译、汇编、链接)_汇编语言_05