C语言条件编译(#if、#else、#elif、#ifdef和#ifndef)详解
在 C语言中,条件编译是一种预处理技术,可以根据不同的条件有选择性地编译代码。我们已经学习了 C语言的 if else 分支结构,而条件编译类似于预处理中的分支结构。
#if 指令的语法格式如下:
由于预处理指令中不使用花括号,因此无法将多条语句组成一条复合语句。因此,需要用 #endif 指令标记指令块结束,并且即使 #if 指令下仅有一条语句,也需要使用 #endif 指令标记指令块结束。
如下是一个使用 #if 指令的示例:
有的同学会有疑惑,为什么有了 if 关键字,还需要使用预处理指令 #if 呢?
例如,上面的示例代码经过预处理后,将被修改为下面的代码:

图 1 预处理分支结构修改代码
下面是一个使用 #else 指令的示例:

图 2 使用#else指令的工作过程
需要注意的是,#if 和 #else 指令都必须与 #endif 指令配对使用,以避免语法错误。
#elif 指令的语法格式如下:
下面是一个使用 #elif 指令的示例:

图 3 使用#elif指令的工作过程
#ifdef 指令的语法格式如下:
下面是一个使用 #ifdef 指令的示例:
与之相反,#ifndef 是一种条件编译指令,用于判断宏是否未定义。#ifndef 指令的语法格式如下:
下面是一个使用 #ifndef 的示例:
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 关键字,还需要使用预处理指令 #if 呢?
- 预处理中的 #if:预处理指令将在编译前,由预处理器处理。预处理器根据预处理指令的意图修改代码。类似于 #define 指令,替换代码中出现的宏。#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指令的工作过程
- 当表达式 N == 1 成立时,保留输出数字的 printf() 函数调用,其他 printf() 函数调用均被删除;
- 当表达式 N == 2 成立时,保留输出字母的 printf() 函数调用,其他 printf() 函数调用均被删除;
- 其他情况下,保留输出星号的 printf() 函数调用,其他 printf() 函数调用均被删除。
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
#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