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

一、程序编译原理

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

  • 第一步(预处理):在程序运行(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---程序编译原理(预处理、汇编、编译、链接)

2.注意事项

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

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

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

三、演示案例

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

  • 第一步:预处理

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

gcc  -E -o  hello.i  hello.c

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

  • 第二步:编译

.s里面是汇编语言

gcc  -S  -o  hello.s  hello.i

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

  • 第三步:汇编

编译生成一个二进制文件

gcc  -c  -o  hello.o  hello.s

  • 第四步:链接

链接生成一个可执行文件

gcc  -o  hello  hello.o

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

./hello

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

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