C语言预处理器

示例

在C编译器开始编译源代码文件之前,将在预处理阶段处理该文件。此阶段可以由单独的程序完成,也可以完全集成到一个可执行文件中。无论如何,在适当的编译开始之前,编译器会自动调用它。预处理阶段通过应用文本替换将您的源代码转换为另一个源代码或翻译单元。您可以将其视为“修改的”或“扩展的”源代码。扩展的源可以作为真实文件存在于文件系统中,也可以仅在存储在存储器中一小段时间,然后再进行进一步处理。

预处理程序命令以井号(“#”)开头。有几个预处理器命令;最重要的两个是:

  1. 定义

    #define主要用于定义常量。例如,

    #define BIGNUM 1000000
    int a = BIGNUM;

    变成

    int a = 1000000;

    #define用这种方式可以避免必须在源代码文件的许多不同位置显式写出某个常数值。如果以后需要更改常量值,这一点很重要。与#define相比,必须在分散在代码中的多个位置进行更改的错误发生要容易得多。

    因为#define只进行高级搜索和替换,所以您也可以声明宏。例如:

    #define ISTRUE(stm) do{stm = stm ? 1 : 0;}while(0)
    // 在函数中:
    a = x;
    ISTRUE(a);

    变成:

    // 在函数中:
    a = x;
    do {
       a = a ? 1 : 0;
    } while(0);

    乍一看,这种效果与内联函数大致相同,但是预处理器不提供#define宏的类型检查。众所周知,这容易出错,使用它们时必须格外小心。

    在此还请注意,预处理器还将用空格替换注释,如下所述。

  2. 包括

    #include用于访问在源代码文件外部定义的函数定义。例如:

     #include <stdio.h> 

    使预处理器在编译之前将的内容粘贴<stdio.h>到#include语句位置的源代码文件中。#include几乎总是用来包含头文件,这些文件主要包含函数声明和#define语句。在这种情况下,我们使用#include以便能够使用诸如printf和的函数scanf,其声明位于file中stdio.h。除非先前已在该文件中声明或定义了函数,否则C编译器不允许您使用该函数。#include因此,语句是在C程序中重用先前编写的代码的方式。

  3. 逻辑运算

    #if defined A || defined B
    variable = another_variable + 1;
    #else
    variable = another_variable * 2;
    #endif

    将更改为:

    variable = another_variable + 1;

    如果之前在项目的某个位置定义了A或B。如果不是这种情况,那么预处理器当然会这样做:

    variable = another_variable * 2;

    这通常用于在不同系统上运行或在不同编译器上编译的代码。由于存在全局定义,它们是特定于编译器/系统的,因此您可以在这些定义上进行测试,并始终让编译器仅使用肯定会使用的代码。

  4. 评论

    预处理器用单个空格替换源文件中的所有注释。注释由表示//到行结束时,或开口的组合/*和关闭*/注释括号。