#if和#ifdef用法详解

在很多的开源文档看到#if和#ifdef这两个语法,可见用途很广泛,今天特地研究了下,做一个总结

语法


情况1:

#ifdef XXXXX
...代码片段1...
#else
...代码片段2...
#endif

如果标识符_XXXX已被#define命令定义过,就运行代码片段1,否则对运行代码片段2。

例:
#define NUM
#ifdef NUM
   NSLOG(@"定义过NUM就执行这里");
#else
   NSLOG(@"没有定义过NUM就执行这里");
#endif
}

如果程序开头有#define NUM这行,即NUM有定义,不管是否为真,和第三者情况比较。碰到下面#ifdef NUM的时候,就执行第一个NSLOG。否则第二个NSLOG将被执行。 这可以很方便的开启/关闭整个程序的某项特定功能,比如用来判断设备类型和iOS版本。


情况2:

#ifndef _XXXX 
...程序段1... 
#else 
...程序段2... 
#endif


这里使用了#ifndef,表示的是if not define。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。


情况3:

#if 常量 
...程序段1...
#else
...程序段2...
#endif 


这里表示,如果常量为真(非0,随便什么数字,只要不是0),就执行程序段1,否则执行程序段2。 这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1就好了。而不要测试的时候,只要将常量变0。


使用场景

下面举例子来说明情况3的实际使用场景: 在ios中,我们经常看到有debug和release两种模式。其实这两种模式分别表示发行版本和调试版本。

他们的区别如下:

  • Debug是调试版本,包括的程序信息更多
  • 只有DEBUG版的程序才能设置断点、单步执行、使用TRACE/ASSERT等调试输出语句。
  • REALEASE不包含任何调试信息,所以体积小、运行速度快。

需求

debug模式下我们需要让程序输出调试信息和nslog,在release版本的时候我们需要屏蔽输出


解决方案一


1、设置DEBUG=1

检查DEBUG标志是否正确定义,xcode一般会在debug运行配置项里面已经定义hao了DEBUG标志,如果没定义我们就自己写上 找到PreProcessor Macros 这个属性,对于Debug配置我们给他写上DEBUG,而在Release配置中把它留空。 这样我们刚才那段预处理命令就可以根据这个标志来判断我们编译的时调试版本还是发布版本,从而控制NSLog的输出


2、设置#ifdef

如下定义在需要实现debug状态下执行,但是release状态不执行的代码

#ifdef DEBUG
#define CLog(format, ...) NSLog(format, ## __VA_ARGS__)
#else
#define CLog(format, ...)
#endif

这里我们判断DEBUG这个宏是否定义,如果有定义我们就将这个CLog宏替换成NSLog调用,而如果没有定义过DEBUG标志,也就是release模式下,我们就不替换,这个时候使用CLog,就不会输出任何东西了


解决方案二

这个方案比上一个方案更加简洁,推荐使用

#ifdef __OPTIMIZE__
# define NSLog(…) {}
#else
# define NSLog(…) NSLog(__VA_ARGS__)
#endif

如果是release版本的时候NSLog这个宏就没有任何作用

解释:
__OPTIMIZE__ 这个宏在release编译的时候Xcode会定义  
把NSLog作为一个宏定义
__VA_ARGS__ 这个是一个可变参数宏  

3、如何切换debug和release版本


参考:

http://www.cnblogs.com/springfield/archive/2011/05/04/2037089.html

comments powered by Disqus