条件编译是根据实际定义宏(某类条件)进行代码静态编译的手段。可根据表达式的值或某个特定宏是否被定义来确定编译条件。
最常见的条件编译是防止重复包含头文件的宏,几乎所有头文件都要采用下述的方法编辑以防止被重复包含,形式跟下面代码类似:
#ifndef ABCD_H
#define ABCD_H
// ... some declaration codes
#endif // #ifndef ABCD_H
在C文件中通常有如下类似的定义:
#ifdef _DEBUG
// ... do some operations
#endif
#ifdef _WIN32
// ... use Win32 API
#endif
常见的条件编译指令
1、#if:如果条件为真,则执行相应的操作。
2、#elif:类似于 elseif 的用法,当前面条件为假,再判断该条件是否为真,如果是真,则执行相应操作。
3、#else:如果前面所有条件均为假,则执行相应操作。
4、#ifdef:如果该宏已定义,则执行相应操作。
5、#ifndef:如果该宏没有定义,则执行相应操作。
6、#endif :结束对应的条件编译指令。(不能省略)
defined :与#if, #elif配合使用,判断某个宏是否被定义
#if,#elif,#else与#endif
#if 指令很像C语言中的 if 语句。#if 后面跟常量表达式,如果表达式为非0,则表达式为真,执行 #if 与 #endif 中间的所有C代码;如果表达式为0,则表达式为假,中间的代码不参与编译。
#if可与常量表达式配合使用。常用格式如下:
#if 常量表达式1
// ... some codes
#elif 常量表达式2
// ... other codes
#elif 常量表达式3
// ...
...
#else
// ... statement
#endif
上面的#if、#elif、#else可以与条件判断语句的if elseif else联系起来理解,同样地,#elif、#else也不是一定需要存在。
常量表达式可以是包含宏、算术运算、逻辑运算等等的合法C常量表达式,如果常量表达式为一个未定义的宏, 那么它的值被视为0。
#if MACRO_NON_DEFINED // 等价于
#if 0
在判断某个宏是否被定义时,应当避免使用#if,因为该宏的值可能就是被定义为0。而应当使用#ifdef或#ifndef。
下面举几个例子:
例1:
#if 0
//代码1
#endif
上面这种用法,相当于#if 0 和 #endif之间的代码被注释掉了,一般在IDE环境中会显示灰色。如果需要这段代码参与编译,那么把#if 0改为#if 1即可。但这种用法最好只是调试阶段临时用,没有太大的现实意义,因为这就跟/* */注释符号类似了。
例2:
#define FUNCTION 0
#if FUNCTION
//代码1
#endif
上面这种用法相对常用,即FUNCTION宏定义为0或者1,决定了#if FUNCTION和#endif之间的代码是否参与编译。
对FUNCTION的宏定义可以放在某个配置用的头文件中,便于集中管控。
例3:
#define FUNCTION 0
#if FUNCTION
//代码1
#else
//代码2
#endif
与例2类似,FUNCTION宏定义为0或者1,FUNCTION为1,则#if FUNCTION和#else之间的代码1参与编译,FUNCTION为0,则#else和#endif之间的代码2参与编译。
例4:
#define FUNCTION 0
#if (FUNCTION == 0)
//代码1
#elif (FUNCTION == 1)
//代码2
#elif (FUNCTION == 2)
//代码3
#endif
FUNCTION宏定义为0或者1或者2,FUNCTION为0,则代码1参与编译,FUNCTION为1,则代码2参与编译,FUNCTION为2,则代码3参与编译。
由于0,1,2不能直观理解,我们还能对0,1,2进行一层宏定义,以增加代码可阅读性,比如:
#define FUN_A 0
#define FUN_B 1
#define FUN_C 2
#define FUNCTION FUN_A
#if (FUNCTION == FUN_A)
//代码1
#elif (FUNCTION == FUN_B)
//代码2
#elif (FUNCTION == FUN_C)
//代码3
#endif
例5:
#define FUN_A 1
#define FUN_B 1
#if (FUN_A && FUN_B)
//代码1
#endif
只有当FUN_A和FUN_B同时定义为1时,代码1才参与编译,否则代码1不参与编译。
例6:
#define FUNCTION 1
#if (FUNCTION < 5)
//代码1
#endif
只有当FUNCTION的定义小于5时,代码1才参与编译,否则代码1不参与编译。
#ifdef,#ifndef,#else与#endif
条件编译中相对常用的预编译指令。模式如下:
#ifdef ABC
// ... codes while definded ABC
#elif (CODE_VERSION > 2)
// ... codes while CODE_VERSION > 2
#else
// ... remained cases
#endif // #ifdef ABC
#ifdef用于判断某个宏是否定义,和#ifndef功能正好相反,二者仅支持判断单个宏是否已经定义,上面例子中二者可以互换。
如果不需要多条件预编译的话,上面例子中的#elif和#else均可以不写。
#ifdef 由于只能判定单个宏是否定义,那么自然没有#if 后面可以判定一个表达式那么多花样,所以就不能举大量的例子了。
#if defined
defined用来测试某个宏是否被定义。defined(name): 若宏被定义,则返回1,否则返回0。
它与#if、#elif、#else结合使用来判断宏是否被定义,乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef。defined可用于在一条判断语句中声明多个判别条件;#ifdef和#ifndef则仅支持判断一个宏是否定义。
类似:
#if defined(VAX) && defined(UNIX) && !defined(DEBUG)
当然,如果是判断单个条件,#if defined和#ifdef没有啥差别。
#if defined(VAX)
和
#ifdef VAX
#if !defined
#if !defined与#ifndef类似,都是用来判断宏没有被定义。
区别在于#if !defined可以判断多个(类似前面的#if defined)。
#if !defined(VAX)
和
#ifndef VAX
这两者效果一样。
#if !defined的本质还是#if defined,所以它们可以组合
#if defined(VAX) && defined(UNIX) && !defined(DEBUG)
这个例子就是当VAX和UNIX都定义了,并且DEBUG没有被定义的情况下,则条件成立。
原文链接:https://blog.csdn.net/weixin_44788542/article/details/130922902
|