在C语言中,程序员可以根据不同的条件,有选择性地编译不同的代码块(忽略其它的代码块),从而产生不同的目标文件,这种机制称为条件编译。
借助条件编译,我们可以在同一份源代码中包含针对不同操作系统、硬件架构或功能配置的代码,而无需维护多个独立的源文件。
条件编译是预处理器的功能,不是编译器的功能。条件编译通过以#开头的预处理命令来完成,包括 #if、#elif、#else、#endif、#ifdef 和 #ifndef。本文先介绍前四个命令,后两个命令请转到:C语言#ifdef和#ifndef命令的用法
条件编译的用法和示例
#if、#elif、#else 和 #endif 允许我们根据特定的条件(一个表达式的值),来决定哪些代码段应该被编译,哪些应该被忽略。它们的基本用法如下:
#if 常量表达式1
//代码段1
//如果 常量表达式1 的值为真,则编译 代码段1,忽略其它代码
#elif 常量表达式2
//代码段2
//如果 常量表达式2 的值为真,则编译 代码段2,忽略其它代码
#elif 常量表达式3
//代码段3
//如果 常量表达式3 的值为真,则编译 代码段3,忽略其它代码
#else
//代码段n
//如果以上表达式的值都为假,则编译 代码段n,忽略其它代码
#endif
整体上的执行流程为:如果常量表达式1的值为真(非 0),就对代码段1进行编译,否则就计算常量表达式2,结果为真的话就对代码段2进行编译,为假的话就继续往下匹配,直到遇到值为真的表达式,或者遇到 #else。
#if #else 命令和 if else 语句的用法非常类似,都是一种分支结构。但是,#if 命令要求判断条件为“常量表达式”,不能包含变量以及函数调用,而 if 语句后面的表达式没有限制,只要符合语法就行。这是 #if 和 if 的一个重要区别。
#if #else 是在预处理阶段进行替换,无法获取变量的值,所以表达式中不能包含变量。
#elif 和 #else 都可以省略,也就是写成下面的形式:
#if 常量表达式
//代码段1
// 如果 常量表达式 的值为真,则编译 代码段1
#else
//代码段2
//如果 常量表达式 的值为假,则编译 代码段2
#endif
或者:
#if 常量表达式
//代码段
//如果 常量表达式 的值为真,则编译这里的 代码段
#endif
示例1:同时使用 #if、#elif 和 #else 命令:
#include
#define LEVEL 2
#if LEVEL == 1
#define MESSAGE "Low priority"
#elif LEVEL == 2
#define MESSAGE "Medium priority"
#elif LEVEL == 3
#define MESSAGE "High priority"
#else
#define MESSAGE "Unknown priority"
#endif
int main() {
printf("Task priority: %s\n", MESSAGE);
return 0;
}
运行结果:
Task priority: Medium priority
我们根据 LEVEL 宏的值来定义不同的 MESSAGE,如果 LEVEL 的值不是 1、2 或 3,那么会使用 #else 分支中定义的默认消息。本例中,第 5~13 行的代码,只有第 8 行代码被编译,其它代码在预处理完成以后就不存在了。
示例2:只使用 #if 命令:
#include
#define DEBUG 1
int main() {
#if DEBUG
printf("Debug mode is enabled.\n");
#endif
//TODO:
return 0;
}
在这个例子中,如果 DEBUG 宏被定义为非零值,那么 printf 语句就会被编译到最终的程序中。否则,这行代码会被忽略。
条件编译的嵌套使用
条件编译命令可以嵌套使用,这使得我们能够创建更加复杂的判断逻辑,请看下面的例子(示例3):
#define DEBUG 1
#define VERBOSE_DEBUG 1
#if DEBUG
printf("Debug mode enabled.\n");
#if VERBOSE_DEBUG
printf("Verbose debug information will be displayed.\n");
#endif
#else
printf("Running in release mode.\n");
#endif
在这个例子中,我们有一个嵌套的条件编译结构。只有当 DEBUG 被定义为非零值时,内部的#if VERBOSE_DEBUG条件才会被检查。
关于 #if 和 #elif 后面的表达式
#if 和 #elif 后面的常量表达式中,可以包含各种算术运算符、逻辑运算符和关系运算符,以实现更复杂的条件判断。请看下面的例子(示例4):
#include
#define M 20
#define N 40
int main(){
#if M+N>100
printf("The value is too large.\n",);
#elif M+N<=100 && M+N>50
printf("The value is right.\n");
#else
printf("The value is too small.\n");
#endif
return 0;
}
运行结果:
The value is right.
虽然这些表达式看起来复杂,但是在程序运行之前就能推算出它们的值;而一旦包含了变量或者函数调用,就必须等到程序运行以后才能获取它们的值,这就超出预处理器的能力了。
总结
C语言条件编译允许只编译源程序中满足条件的代码段,使生成的目标程序较短,从而减少了内存的开销,并提高了程序的效率。
最后请注意,#endif 不能省略,它必须和 #if 配对出现,用以结束条件编译。