第十四章、编译预处理

你还记得一个写好的 C 语言程序文件最终编译成可执行程序需要几步吗?

当一个编写好的 .c 文件通过编译器变为二进制可执行文件一共经过四个阶段。

这四个阶段分别是:

  1. 预处理(Preprocessing)。
  2. 编译(Compilation)。
  3. 汇编(Assembly)。
  4. 连接(Linking)。

这一章我们先学习 C 语言的编译的第一步,编译预处理的指令。

C 语言的预处理指令都是以英文的井号(#)开头,在编译器进行正式编译之前执行。

预处理指令有如下几种:

  1. 文件包含指令:#include
  2. 宏定义指令:#define
  3. 取消宏定义指令:#undef
  4. 条件编译指令,#if#endif等。
  5. 停止编译报错指令 #error
  6. 编译参数设定 #pragma

这一章我们先学习前五种预处理指令。

1. 文件包含

文件包含指令 是以 #include 开头的指令,它的作用主要是在预处理阶段将其它文件的内容插入到当前文件。

使用 文件包含 的好处是当多个文件都需要使用一段共有代码的时候,每个文件都抄写一份这段代码,这增大了工作量,同时也不方便程序的修改。在这种情况下我们可以将这段共有代码放入到一个文件中,然后使用文件包含指令 #include 插入到需要使用这段代码的文件中即可。

在 C 语言中。一般函数的声明或者变量的声明等共有代码通常放入一个 .h 为后缀的文件中。我们把这个以 .h 结尾的文件称为头文件。因为这部分代码通常放在一个文件的最上端。

文件包含的语法有两种

// 方法1
#include <文件路径>
// 方法2
#include "文件路径"

说明:

  1. #include <文件路径> 优先查找系统文件的路径,如果没有才查找本地路径。
  2. #include "文件路径" 优先查找本地的路径,如果没有才查找系统文件路径。
  3. 文件路径 一般使用相对路径。

示例:

以下我们使用多个文件来实现打印一行 hello world!

文件 print.c 内容如下:

printf("hello world!\n");

文件 main.c 内容如下:

#include <stdio.h>

int main(int argc, char *argv[]) {

#include "print.c"

    return 0;
}

使用 GCC 编译 main.c 运行结果如下:

weimingze@mzstudio:~$ gcc -o hello main.c
weimingze@mzstudio:~$ ./hello
hello world!

可见, #include "print.c"print.c 中的内容 printf("hello world!\n"); 插入到了 main 函数中。

实验:

完成上述示例代码的编写。然后使用自己的编译器查看预处理后的 main.c 文件的内容。如在 GCC 编译器下可以使用如下命令查看预处理后的结果。

gcc -E main.c