首页 > 编程笔记 > C语言笔记 阅读:43

C语言条件编译(#if、#else、#elif、#ifdef和#ifndef)详解

在 C语言中,条件编译是一种预处理技术,可以根据不同的条件有选择性地编译代码。我们已经学习了 C语言的 if else 分支结构,而条件编译类似于预处理中的分支结构。

C语言#if指令

在 C语言中,#if 也是一种条件编译指令,它可以根据某个常量表达式的值有选择性地编译代码。

#if 指令的语法格式如下:
#if 常量表达式
    编译的代码段
#endif
#if 指令要求条件表达式为一个常量表达式,其中不允许出现变量。此外,#if 指令还会将常量表达式的值计算出来,并根据计算结果选择是否编译代码段:
由于预处理指令中不使用花括号,因此无法将多条语句组成一条复合语句。因此,需要用 #endif 指令标记指令块结束,并且即使 #if 指令下仅有一条语句,也需要使用 #endif 指令标记指令块结束。

如下是一个使用 #if 指令的示例:
#include <stdio.h>
#define N 0
int main()
{
#if N == 1   //  常量表达式,无须括号
   printf("111111\n");
   printf("222222\n");
   printf("333333\n");
#endif      //  必须使用#endif指令标记指令块结束
   printf("AAAAAA\n");
   printf("BBBBBB\n");
   printf("CCCCCC\n");
   return 0;
}
运行结果为:

AAAAAA
BBBBBB
CCCCCC

被 #if 和 #endif 指令包括的代码段不符合条件,因此这段代码并没有被执行。

有的同学会有疑惑,为什么有了 if 关键字,还需要使用预处理指令 #if 呢?
例如,上面的示例代码经过预处理后,将被修改为下面的代码:
#include <stdio.h>
int main()
{
    printf("AAAAAA\n");
    printf("BBBBBB\n");
    printf("CCCCCC\n");
    return 0;
}
如下图所示,由于在预处理时就需要计算条件表达式 N == 1 的结果,此时程序还未编译并运行,不能使用任何变量,因此条件表达式必须为一个常量表达式。另外,N 是由 #define 定义的符号常量,值为 0,表达式结果为假。因此,由 #if 到 #endif 组成的指令块中的代码将被删除。


图 1 预处理分支结构修改代码

C语言#else指令

在 C语言中,#else 是一种条件编译指令,用于在 #if 指令的条件不成立时执行某段代码。#else 指令的语法格式如下:
#if 常量表达式
    编译的代码段1
#else
    编译的代码段2
#endif
#if 指令计算常量表达式的值,并根据计算结果有选择性地编译代码段 1 或代码段 2。如果常量表达式的值为真,则编译代码段 1;否则编译代码段 2。

下面是一个使用 #else 指令的示例:
#include <stdio.h>
#define N 0
int main()
{
#if N == 1
   printf("111111\n");
   printf("222222\n");
   printf("333333\n");
#else
   printf("AAAAAA\n");
   printf("BBBBBB\n");
   printf("CCCCCC\n");
#endif
   return 0;
}
在上文的示例代码中,无论表达式 N == 1 结果为真或假,后三条函数 printf() 调用都不受影响。但是使用 #else 指令后,它与 #endif 指令将后三条函数 printf() 组成指令块。仅当 N == 1 结果为假时,后三条函数 printf() 调用语句才得以保留,如下图所示:


图 2 使用#else指令的工作过程

需要注意的是,#if 和 #else 指令都必须与 #endif 指令配对使用,以避免语法错误。

C语言#elif指令

在 C语言中,#elif 也是一种条件编译指令,用于在多个条件中选择一个条件执行某段代码。#elif 指令可以与 #if 或 #elif 指令一起使用,用于表示“否则,如果”的意思。

#elif 指令的语法格式如下:
#if 常量表达式1
   编译的代码段1
#elif 常量表达式2
   编译的代码段2
#elif 常量表达式3
   编译的代码段3
...
#else
   编译的代码段N
#endif
当 #if 指令中的常量表达式 1 为假时,依次判断下一个 #elif 指令中的常量表达式,直到找到一个为真的常量表达式,编译相应的代码段。如果所有的常量表达式都为假,则编译 #else 指令中的代码段 N。

下面是一个使用 #elif 指令的示例:
#include <stdio.h>
#define N 0
int main()
{
#if N == 1
    printf("111111\n");
    printf("222222\n");
    printf("333333\n");
#elif N == 2
    printf("AAAAAA\n");
    printf("BBBBBB\n");
    printf("CCCCCC\n");
#else
    printf("******\n");
#endif
    return 0;
}
查看下图:


图 3 使用#elif指令的工作过程
 

C语言#ifdef指令和#ifndef指令

在 C语言中,#ifdef 是一种条件编译指令,用于判断宏是否已经定义。

#ifdef 指令的语法格式如下:
#ifdef 宏名
    编译的代码段
#endif
#ifdef 指令会根据宏名是否已经定义,选择是否编译代码段。若定义了该宏,则保留指令块内的代码;否则,删除代码块内的代码。

下面是一个使用 #ifdef 指令的示例:
#include <stdio.h>
#define printNumber
int main()
{
#ifdef printNumber
    printf("111111\n");
    printf("222222\n");
    printf("333333\n");
#endif
#ifdef printLetter
    printf("AAAAAA\n");
    printf("BBBBBB\n");
    printf("CCCCCC\n");
#endif
    return 0;
}
运行结果为:

111111
222222
333333

该程序中定义了宏 printNumber,在 #ifdef printNumber 中使用了该宏,因此保留了输出数字的 printf() 函数调用,而指令 #ifdef printLetter 会删除输出字母的 printf() 函数调用。

与之相反,#ifndef 是一种条件编译指令,用于判断宏是否未定义。#ifndef 指令的语法格式如下:
#ifndef 宏名
    编译的代码段
#endif
#ifndef 指令会根据宏名是否未定义,选择是否编译代码段。若未定义该宏,则保留指令块内的代码;否则,删除代码块内的代码。

下面是一个使用 #ifndef 的示例:
#include <stdio.h>
#define printNumber
int main()
{
#ifndef printNumber
    printf("111111\n");
    printf("222222\n");
    printf("333333\n");
#endif
#ifndef printLetter
    printf("AAAAAA\n");
    printf("BBBBBB\n");
    printf("CCCCCC\n");
#endif
   return 0;
}
运行结果为:

AAAAAA
BBBBBB
CCCCCC

该程序中定义了宏 printNumber,在 #ifndef printNumber 中使用了该宏,因此删除了输出数字的 printf() 函数调用,而保留了输出字母的 printf() 函数调用。

相关文章