#if #ifdef #ifndef的用法——条件编译
假如现在要开发一个C语言程序,让它输出红色的文字,并且要求跨平台,在 Windows 和 Linux 下都能运行,怎么办呢?
这个程序的难点在于,不同平台下控制文字颜色的代码不一样,我们必须要能够识别出不同的平台。
Windows 有专有的宏_WIN32
,Linux 有专有的宏__linux__,此时可以使用预处理命令进行条件编译。
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> int main(){ #if _WIN32 system( "color 0c" ); printf( "http://c.biancheng.net\n" ); #elif __linux__ printf( "\033[22;31mhttp://c.biancheng.net\n\033[22;30m" ); #else printf( "http://c.biancheng.net\n" ); #endif return 0; } |
#if、#elif、#else 和 #endif 都是预处理命令,整段代码的意思是:如果宏 _WIN32 的值为真,就保留第 4、5 行代码,删除第 7、9 行代码;如果宏 __linux__ 的值为真,就保留第 7 行代码;如果所有的宏都为假,就保留第 9 行代码。
这些操作都是在预处理阶段完成的,多余的代码以及所有的宏都不会参与编译,不仅保证了代码的正确性,还减小了编译后文件的体积。
这种能够根据不同情况编译不同代码、产生不同目标文件的机制,称为条件编译。条件编译是预处理程序的功能,不是编译器的功能。
条件编译需要多个预处理命令的支持。
#if 的用法
1 2 3 4 5 6 7 8 9 | #if 整型常量表达式1 程序段1 #elif 整型常量表达式2 程序段2 #elif 整型常量表达式3 程序段3 #else 程序段4 #endif |
它的意思是:如常“表达式1”的值为真(非0),就对“程序段1”进行编译,否则就计算“表达式2”,结果为真的话就对“程序段2”进行编译,为假的话就继续往下匹配,直到遇到值为真的表达式,或者遇到 #else。这一点和 if else 非常类似。
需要注意的是,#if 命令要求判断条件为“整型常量表达式”,也就是说,表达式中不能包含变量,而且结果必须是整数;而 if 后面的表达式没有限制,只要符合语法就行。这是 #if 和 if 的一个重要区别。
#ifdef 用法的一般格式为:
1 2 3 4 5 | #ifdef 宏名 程序段1 #else 程序段2 #endif |
它的意思是,如果当前的宏已被定义过,则对“程序段1”进行编译,否则对“程序段2”进行编译。
也可以省略 #else:
1 2 3 | #ifdef 宏名 程序段 #endif |
实际应用中的例子
VS/VC 有两种编译模式,Debug 和 Release。在学习过程中,我们通常使用 Debug 模式,这样便于程序的调试;而最终发布的程序,要使用 Release 模式,这样编译器会进行很多优化,提高程序运行效率,删除冗余信息。
为了能够清楚地看到当前程序的编译模式,我们不妨在程序中增加提示,请看下面的代码:
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> #include <stdlib.h> int main(){ #ifdef _DEBUG printf( "正在使用 Debug 模式编译程序...\n" ); #else printf( "正在使用 Release 模式编译程序...\n" ); #endif system( "pause" ); return 0; } |
当以 Debug 模式编译程序时,宏 _DEBUG 会被定义,预处器会保留第 5 行代码,删除第 7 行代码。反之会删除第 5 行,保留第 7 行。
#ifndef 的用法
1 2 3 4 5 | #ifndef 宏名 程序段1 #else 程序段2 #endif |
与 #ifdef 相比,仅仅是将 #ifdef 改为了 #ifndef。它的意思是,如果当前的宏未被定义,则对“程序段1”进行编译,否则对“程序段2”进行编译,这与 #ifdef 的功能正好相反。
三者之间的区别
最后需要注意的是,#if 后面跟的是“整型常量表达式”,而 #ifdef 和 #ifndef 后面跟的只能是一个宏名,不能是其他的。
例如,下面的形式只能用于 #if:
1 2 3 4 5 6 7 8 9 10 | #include <stdio.h> #define NUM 10 int main(){ #if NUM == 10 || NUM == 20 printf( "NUM: %d\n" , NUM); #else printf( "NUM Error\n" ); #endif return 0; } |
运行结果:
NUM: 10
再如,两个宏都存在时编译代码A,否则编译代码B:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <stdio.h> #define NUM1 10 #define NUM2 20 int main(){ #if (defined NUM1 && defined NUM2) //代码A printf( "NUM1: %d, NUM2: %d\n" , NUM1, NUM2); #else //代码B printf( "Error\n" ); #endif return 0; } |
运行结果:
NUM1: 10, NUM2: 20
#ifdef 可以认为是 #if defined 的缩写。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~