编译预处理
- 预处理,就是在编译之前做的事情,所以预处理也叫预编译。预处理是Objective-C提供的一个重要功能。本文主要介绍编译预处理的3种指令:宏定义、“文件包含”处理及条件编译。
1.宏定义
- 宏是一种批量处理的称谓。一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符串)。这种替换在预编译时进行,称作宏展开。
- 在Objective-C程序中,宏可以简单的理解为一个被赋予名字的代码段。当这个名字出现在代码中被使用的时候,就会被替换成相应的代码段。宏一般可以认为有两种存在(或者说是使用)形式,一种是类似于对象的宏,我们可以不那么严格的说成是宏对象,另一种是类似于方法的宏,我们姑且称之为宏方法;也可以根据有无参数来分为有参数宏和无参数宏。
- 宏的创建形式也很简单,用
#define
指令,后面跟上宏的名字和被替换的代码。 -
注意:宏的名称通常都是用大写字母
1.无参数宏定义如下:
#define HEIGHT 60.0f
#define SCREENWIDTH [UIScreen mainScreen].bounds.size.width
无参数宏通常用来定义一个常量
2.有参数宏定义如下:
//获取两个数的最小值和最值
#define MIN(A,B) ( (A) > (B) ? (B) : (A) )
#define MAX(A,B) ( (A) > (B) ? (A) : (B) )
注意:宏定义的变量在引用的时候,用 ()括起来,防止预处理器展开的错误
3.当一个宏的表达式很长时,可以在每行后面用反斜杠""来连接(作用屏蔽换行符),表明宏是一整段表达式;
//获取三个数最大值
#define MAXVALUE(A,B,C) ({\
int D = A>B?A:B;\
C>D?C:D;\
})
NSLog(@"最大值:%zd",MAXVALUE(10, 20,30));
结果:
4.关于#与##的操作符
<1>“#”的功能是将其后面的宏参数进行字符串化操作,意思就是对它所应用的宏变量通过替换后在其左右各加上一个双引号。
#define STRING(A) ({\
printf(#A);\
})
STRING(ABCD);
结果
<2>连接符##用来将两个token连接为一个token,但它不可以位于第一个token之前or最后一个token之后。注意这里连接的对象只要是token就行,而不一定是宏参数,但是##又必须位于宏定义中才有效,因其为编译期概念(比较绕)。
示例子可见:OC单例模式详解
5.宏取消
宏定义必须写在方法之外,其作用域为宏定义命令起到程序结束;如果我们想在程序的某一个地方终止宏的作用域,就要使用
#undef
命令。
#define A 20
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@" 最大值:%zd",A);
#undef A
NSLog(@" 最大值:%zd",A);
}
结果可见:由于在41行时取消了宏,此后再调用宏时就会报错
2.文件包含
- 所谓“文件包含”处理,是指一个源文件可以将另外一个源文件的全部内容包含进来,即将另外的文件包含到本文件中。文件包含是Objective-C预处理程序的另一个重要的功能。Objective-C提供了
#import
命令用来实现“文件包含”的操作。
注意:“”引入的创建的文件,<>引入的系统文件。 - 在一个被包含文件中又可以包含另一个被包含文件,即文件包含是可以嵌套的。
- 被包含文件与包含文件在预编译后已成为同一个文件,而不再是两个文件了。
3.条件编译
1.#ifdef
使用:
作用是当标识符已经被定义过(一般使用
#define
进行定义),就对程序段1进行编译,否则编译程序段2。
#define X
- (void)viewDidLoad {
[super viewDidLoad];
#ifdef X
NSLog(@"定义过了X");
#else
NSLog(@"未定义过了X");
#endif
}
结果:
- 在有的时候,
#else
可以省去不用
#define X
- (void)viewDidLoad {
[super viewDidLoad];
#ifdef X
NSLog(@"定义过了X");
#endif
}
结果:
2.
#ifndef
使用:- 它的作用是当标识符没有被定义时,就对程序段1进行编译;当标识符被定义过,就对程序段2进行编译,与
#ifdef
作用相反。 -
ifndef
和ifdef
一样,也可以将#else
去掉。
- (void)viewDidLoad {
[super viewDidLoad];
#ifndef X
NSLog(@"未定义过了X");
#endif
}
3.
#if
使用#if
预处理程序语句提供控制条件编译的更加通用的方法。