2014-03-13周四:ifndef条件编译和宏开关解析

来自http://hi.baidu.com/shiwl111/item/e695a40e8489ce9aa2df4373

#define TEST //定义了TEST

int main(){
{
#ifdef TEST //定义了TEST,所以这里的ifdef为真
cout<<"I love you"<<endl;//因此编译的时候会编译这句
#else
cout<<"I hate you"<<endl;//于是,这句就编译不到
#endif /*TEST*/

return 0;
}

所以实际代码是
int main()
{
cout<<"I love you"<<endl;
return 0;
}

假如把#define TEST去掉或者在#ifdef之前使用了#undef TEST的话
那么实际的代码是
int main()
{
cout<<"I hate you"<<endl;
return 0;
}

通常这样的宏叫做宏开关,有很多用处
1.譬如:
注释掉一大段代码,把这段代码用
#if 0 //也可以用#ifdef NONONO,这里的NONONO是随意的,只要没有define过就行,但是#if 0更方便
这里是一大段代码 //这段代码编译的时候就编译不到了
#endif 

2.再如:
通常用在头文件中
假如头文件myheader.h

会这样写这个文件

#ifndef __MYHEADER_H__ //注意,是ifndef,表示"假如没有定义",这里的__MYHEADER_H__是任意定的,但通常会使用这样的头文件名的大写字母形式,因为这样可以保证这个宏的名字是唯一的
#define __MYHEADER_H__

void func(void){}

#endif /*__MYHEADER_H__*/ //加上这个注释是比较好的习惯,有始有终,方便阅读

这通常叫做编译守卫

这样做的好处就是假如在同一个.c文件中不小心或者故意包含了2次或者2次以上同一个头文件时,不会出现错误
假如我在一个.c文件中这样写
#include "myheader.h"
#include "stdlib.h"
#include "myheader.h"

int main(){}

这段代码等价于
#ifndef __MYHEADER_H__ 
#define __MYHEADER_H__

void func(void){}

#endif /*__MYHEADER_H__*

#include "stdlib.h"

#ifndef __MYHEADER_H__ 
#define __MYHEADER_H__

void func(void){}

#endif /*__MYHEADER_H__*

假如不用这个条件编译,
那么就是
void func(void){}
#include "stdlib.h"
void func(void){}
编译时会出错,因为函数func重定义了

用了条件编译的话
#ifndef __MYHEADER_H__ //判断是否"没有定义这个宏开关"
#define __MYHEADER_H__//确实没有定义,那么现在定义这个宏开关

void func(void){}

#endif /*__MYHEADER_H__*

#include "stdlib.h"

#ifndef __MYHEADER_H__ //判断是否"没有定义这个宏开关"
#define __MYHEADER_H__ //上面定义过了,所以这里编译不到
void func(void){}//这里也编译不到
#endif /*__MYHEADER_H__*
所以就相当于
#ifndef __MYHEADER_H__ //判断是否"没有定义这个宏开关"
#define __MYHEADER_H__//确实没有定义,那么现在定义这个宏开关
void func(void){}
#endif /*__MYHEADER_H__*
#include "stdlib.h"


也就避免了这种情况下发生的重定义错误(其实这里这么做,同工程下的不同的c都包含这个.h的话还是会出错,但是至少同一个.c数次包含这个.h的错误就避免了)
3.还有:
譬如给一个手机做一个通话记录的功能
假如我定义了一个宏#define CALL_LOG
然后
#ifdef CALL_LOG
这里是实现CALL_LOG功能的代码
#endif /*CALL_LOG*/
并且,其他地方,只要和CALL_LOG有关的代码都用这个#ifdef CALL_LOG #endif包起来,那么,如果某个版本的手机不需要这个功能了,只要把#define CALL_LOG注释掉,或者在后面紧跟一句#undef CALL_LOG就可以了,而不必要把和CALL_LOG相关的代码都注释掉或者删除掉,因为这些相关代码可能分散在很多.c文件中,手动去删或者注释的话会很傻,一般就这样使用的。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值