C 预处理器和宏

本文讨论了 C 语言中的预处理器,并通过实例介绍了 #include#define 和条件编译。

在 C 程序被编译之前,需要一些处理工作,比如引入头文件等。 C 语言定义了一些指令来完成这些工作,比如 #include#define,这些指令被称为预处理器。

C 语言编程中预处理器的工作

C 预处理器是编译之前的预处理步骤,这包括包含头文件,宏定义,条件编译等。整个过程可以简单的理解为一个文本替换的过程。比如包含头文件,预处理器简单的将头文件的源文件替换到此位置后,然后才进行编译。

所有预处理指令都以 # 符号开头。例如,

#define PI 3.14

C 预处理器的一些常见用途是:

  • 包含头文件
  • 定义宏
  • 条件编译

使用 #include 包含头文件:

#include 预处理器用来包含头文件到 C 程序。例如,

#include <stdio.h>

这里, stdio.h 是一个头文件。#include 预处理器指令用来包含 stdio.h 头文件中的内容到当前文件中。

这就是为什么您需要先使用 #include <stdio.h>,然后才能使用 scanf()printf() 之类的函数的原因。

您还可以创建自己的包含函数声明的头文件,并使用 #include 预处理器指令将其包含在您的程序中。

#include "my_header.h"

使用 #define 定义宏

宏是给定名称的代码片段。您可以使用 #define 预处理器指令在 C 中定义宏。

如下示例:

#define c 299792458  // 光速

在这里,当我们在我们的程序中使用 c 时,它被替换为 299792458 .

示例 1:宏定义

#include <stdio.h>
#define PI 3.1415

int main()
{
    float radius, area;
    printf("Enter the radius: ");
    scanf("%f", &radius);

    // Notice, the use of PI
    area = PI * radius * radius;

    printf("Area=%.2f",area);
    return 0;
}

宏定义函数

除了上面的宏定义,我们可以使用宏定义函数。宏定义函数调用方式和函数类似。例如,

#define circleArea(r) (3.1415*(r)*(r))

程序每次遇到 circleArea(argument) ,就用 (3.1415*(argument)*(argument)) 替换。

假设,我们将 5 作为参数传递给宏定义函数,那么 circleArea(5) 被替换为 (3.1415*5*5)

示例 2:宏定义和宏定义函数

#include <stdio.h>
#define PI 3.1415
#define circleArea(r) (PI*r*r)

int main() {
    float radius, area;

    printf("Enter the radius: ");
    scanf("%f", &radius);
    area = circleArea(radius);
    printf("Area = %.2f", area);

    return 0;
}

条件编译

在 C 语言编程中,您可以指示预处理器是否包含代码块。为此,可以使用条件指令。

它类似于 if 声明,但又有一个主要区别:

if 在执行期间测试该语句以检查是否应执行代码块,而条件编译用于在执行之前的编译阶段确定是否包含或跳过某个代码块。

条件编译的用途

  • 根据机器、操作系统使用不同的代码
  • 在两个不同的程序中编译相同的源文件
  • 从程序中排除某些代码,但保留它作为将来的参考

如何使用条件编译?

使用 #ifdef#if#defined#else#elseif 指令来进行条件编译。

#ifdef 指令

#ifdef MACRO
   // 条件代码
#endif

这里,条件代码仅在 MACRO 被定义的情况下才包含在程序中。

#if、#elif 和 #else 指令

#if expression
   // 条件代码
#endif

这里, expression 是整数类型的表达式(可以是整数、字符、算术表达式、宏等)。

条件代码仅在 expression 的结果为非零值的情况下才包含在程序中。

可选 #else 指令可以与 #if 指令一起使用。

#if expression
   // 如果表达式结果不为 0,包含此处的代码
#else
   // 如果表达式结果为 0,包含此处的代码
#endif

您还可以将嵌套条件 #elif 添加到 #if...#else 中间:

#if expression
    // 如果 expression 结果不为 0,包含此处的代码
#elif expression1
    // 如果 expression1 结果不为 0,包含此处的代码
#elif expression2
    // 如果 expression2 结果不为 0,包含此处的代码
#else
    // 如果所有表达式结果为 0,包含此处的代码
#endif

defined

特殊运算符 defined 用于测试是否定义了某个宏。它经常用在 #if 指令中。

#if defined BUFFER_SIZE && BUFFER_SIZE >= 2048
  // codes

预定义宏

以下是 C 语言编程中的一些预定义宏。

说明
__DATE__ 表示当前编译日期的字符串
__FILE__ 表示当前文件名的字符串
__LINE__ 表示当前行号的整数
__STDC__ 如果遵循 ANSI 标准 C,则该值为非零整数
__TIME__ 表示当前编译时间的字符串

示例 3:获取当前编译时间

以下程序使用 __TIME__ 宏输出当前编译时间。

#include <stdio.h>
int main()
{
   printf("Current time: %s",__TIME__);
}

输出

Current time: 19:54:39