条件编译

什么是条件编译

—般情况下,C语言源程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译。此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译(conditional compile)。
不用条件编译命令而直接用if语句也能达到要求,那么用条件编译命令有什么好处呢?的确,很多问题完全可以不用条件编译处理,但那样做目标程序长(因为所有语句都编译)。而采用条件编译,可以减少被编译的语句,从而减少目标的长度。当条件编译段比较多时,目标程序长度可以大大减少。

条件编译的命令主要包括以下:
#define       定义一个预处理宏
#undef        取消宏的定义

#if           编译预处理中的条件命令,相当于C语法中的if语句
#ifdef        判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef       与#ifdef相反,判断某个宏是否未被定义
#elif         若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else         与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif        #if, #ifdef, #ifndef这些条件命令的结束标志.
defined       与#if, #elif配合使用,判断某个宏是否被定。
条件编译的好处

1.可通过编译器命令行定义预处理器使用的宏 。
2.条件编译可以避免重复包含同一个头文件 。
3.条件编译在工程开发中可以区别不同产品线的代码 。
4.条件编译可以定义产品的发布版和调试版。

条件编译的用途解析

宏定义

可使用#define和#undef定义及取消定义一个宏。

宏定义,按照是否带参数通常分为对象宏、函数宏两种。
对象宏: 不带参数的宏被称为”对象宏(objectlike macro)”。对象宏多用于定义常量、通用标识。
例如:

// 常量定义
#define MAX_LENGTH 100
// 通用标识,日志输出宏
#define SLog printf
// 预编译宏
#define _DEBUG

函数宏:带参数的宏。
利用宏可以提高代码的运行效率:子程序的调用需要压栈出栈, 这一过程如果过于频繁会耗费掉大量的CPU运算资源。 所以一些代码量小但运行频繁的代码如果采用带参数宏来实现会提高代码的运行效率。但多数c++程序不推荐使用函数宏,调试上有一定难度,可考虑使用c++的inline代替之。例如:

// 最小值函数
#define MIN(a,b) ((a)>(b)? (a):(b))
// 安全释放内存函数
#define SAFE_DELETE(p) {if(NULL!=p){delete p; p = NULL;}}

#undef可以取消宏定义,与#define对应。

防止重复包含头文件

#include的本质是将已经存在的文件内容嵌入到当前文件中。
#include的间接包含同样会产生嵌入文件内容的动作。
因此,可能会出现某一个头文件被多次包含的情况,这样可能会产生错误。
如果使用条件编译,可以随心所欲的包含头文件。

#ifndef _HEADER_H_
#define _HEADER_H_
    //头文件的内容
#endif
不同的产品线共用一份代码&区分编译产品的调试版和发布版

举例说明:

#include <stdio.h>

#ifdef DEBUG
    #define LOG(s) printf("[%s:%d] %s\n", __FILE__, __LINE__, s)
#else
    #define LOG(s) NULL
#endif

#ifdef HIGH
void f()
{
    printf("This is the high level product!\n");
}
#else
void f()
{
}
#endif

int main()
{
    LOG("Enter main() ...");

    f();

    printf("1. Query Information.\n");
    printf("2. Record Information.\n");
    printf("3. Delete Information.\n");

    #ifdef HIGH
    printf("4. High Level Query.\n");
    printf("5. Mannul Service.\n");
    printf("6. Exit.\n");
    #else
    printf("4. Exit.\n");
    #endif

    LOG("Exit main() ...");

    return 0;
}

对于上面的程序,使用gcc -DDEBUG test.c 可以编译调试版。使用gcc -DHIGH test.c 可以编译高级版本。
加上-D选项就是在编译时增加对-D后面的宏的定义。也可以用-D name=definition,来通过命令窗口对宏进行定义。
gcc还有与-D对应的另一个参数-U用于取消宏。

补充

defined

defined用来测试某个宏是否被定义。defined(name): 若宏被定义,则返回1,否则返回0。
它与#if、#elif、#else结合使用来判断宏是否被定义,乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef。defined可用于在一条判断语句中声明多个判别条件;#ifdef和#ifndef则仅支持判断一个宏是否定义。

#if defined(VAX) && defined(UNIX) && !defined(DEBUG) 

和#if、#elif、#else不同,#ifdef、#ifndef、defined测试的宏可以是对象宏,也可以是函数宏。

#if

常量表达式可以是包含宏、算术运算、逻辑运算等等的合法C常量表达式,如果常量表达式为一个未定义的宏,那么它的值被视为0。

#if MACRO_NON_DEFINED 
// 等价于
#if 0

在判断某个宏是否被定义时,应当避免使用#if,因为该宏的值可能就是被定义为0。而应当使用#ifdef或#ifndef。

注意:#if、#elif之后的宏只能是对象宏。如果宏未定义,或者该宏是函数宏,则编译器可能会有对应宏未定义的警告。

参考:
1.https://blog.csdn.net/qq_33658067/article/details/79443014
2.https://blog.csdn.net/qq_36016407/article/details/54946352
3.https://blog.csdn.net/joeblackzqq/article/details/6785256

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值