2.16 预处理
前面的内容中,我们已经多次看到预处理的使用,如#define、#ifndef、#endif等指令,它们以行为单位,而且结尾没有分号,这是预处理和代码最大的区别之一。
下面,我们将会对常用的预处理指令做一些总结,主要包括:
❑ #define和#undef指令。
❑ 条件编译指令。
❑ #import指令。
■2.16.1 #define和#undef指令
#define指令的功能就是定义宏,我们可以定义很简单的宏,简单到只有一个标识名称,如下面的代码。
#define DEBUG
这样,就可以根据是否定义了这个宏来判断项目是在调试中,还是正式发布了,我们可以使用#ifdef指令判断一个宏是否已定义,而使用#ifndef指令判断一个宏是否没有定义。
使用#define指令定义的宏,可以使用#undef指令撤消,如下面的代码。
#undef DEBUG
#define指令的另一个功能就是模拟定义常量,如下面的代码。
#define DT_IPHONE4 4 #define DT_IPHONE5 5 #define DT_IPAD 1000
此外,我们还可以利用#define定义一些复杂的宏,如下面的代码。
#define IsEvenNumber(n) (n % 2 == 0)
其中,我们定义了IsEvenNumber宏,其功能是判断一个数是否为偶数,它使用起来和函数类似,如下面的代码。
int num = 100; if (IsEnenNumber(num)) { NSLog(@"%i是偶数", num); }else{ NSLog(@"%i不是偶数", num); }
此外,如果一个#define指令的定义过长,我们可以将它们分行,但需要使用“\”符号放在前一行的结尾处,用以说明下一行与本行是同一指令。
■2.16.2 条件编译指令
通过定义宏,还可以指定在不同的条件下编译不同的代码,此时,我们可以使用#define定义一些与系统平台相关的标识,然后根据这些标识将软件编译成不同的版本。与条件编译相关的指令包括:
❑ #ifdef指令,判断一个宏标识是否已定义。
❑ #ifndef指令,判断一个宏标识是否没有定义。
❑ #endif指令,与#ifdef或#ifndef指令组成一个代码块。
❑ #elif和#else指令,一般与#ifdef和#endif指令组合使用,以判断不同条件下的代码执行情况。
如下面的代码,将根据不同的设备类型来编译相应的代码。
#define IPhone #ifdef IPhone // iPhone设备代码 #elif IPad // iPad设备代码 #else // 其他类型设备代码 #endif
此外,在头文件中,如前面我们定义的CApp.h文件,其中使用了一个模式化的预处理代码,我们再来看一看。
#ifndef __CApp_h__ #define __CApp_h__ #endif
这三个预处理指令的功能是在代码文件中防止多次包含头文件,以提高代码的编译效率。
■2.16.3 #import指令
#import指令的功能就是引用头文件,我们已经多次使用,再次说明一下:
❑ 使用一对尖括号<>引用的头文件是系统资源,如Foundation.h文件。
❑ 使用一对双引号""引用的头文件是“外部”资源,可能是第三方框架或自定义的头文件。