关于宏定义相信大家一定不会陌生,我们经常使用的都是一些简单的宏定义常量,或者使用宏定义一个方法。但是在项目中会使用到很多你真的理解宏定义的语法吗?
下面来展示一些宏定义的用法:
1.使用宏定义定义一个常量
//This defines PI
#define M_PI 3.14159265358979323846264338327950288
2.使用宏定义定义一个func
//this define a MIN()
#define MIN(A,B) (A<B?A:B)
这些对大家来说可能都是很常见的,但是#define的高级用法在下面。
3.宏定义的嵌套
#define USER_GLOBAL(obj, userType) _USER_CORE(obj, @#userType, nil)
#define _USER_CORE(obj, strType, strGroup) [AppUser apply:obj withUserType:strType withGroup:strGroup]
使用简单的宏替代很长的方法,实现参数的传递
ps:@# 是字符化操作符,将传入的单字符操作名转化为字符
下面详细解释一下宏定义中的#、##、@#、\操作符的使用
“#”:字符串化操作符,作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串。使用条件:只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前
举例:
#define example1(instr) #instr
string str=example1(abc); 将会展成:string str="abc";
注意:对空格的处理
a、忽略传入参数名前面和后面的空格。
如:str=example1( abc ); 将会被扩展成 str="abc";
b、当传入参数名间存在空格时,编译器将会自动连接各个子字符串,用每个子字符串中只以一个空格连接,忽略其中多余一个的空格。
如:str=exapme1( abc def); 将会被扩展成 str="abc def";
“##”: 符号连接操作符,作用:将宏定义的多个形参名连接成一个实际参数名,使用条件:只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前
#define exampleNum(n) num##n
int num=exampleNum(9); 将会扩展成 int num=num9;
注意:
1、当用##连接形参时,##前后的空格可有可无。
如:#define exampleNum(n) num ## n 相当于 #define exampleNum(n) num##n
2、连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义
@#:名称:字符化操作符 作用:将传入的单字符参数名转换成字符,以一对单引用括起来。使用条件:只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。
举例:
#define makechar(x) @#X
a = makechar(b); 展开后变成了:a= 'b';
\ : 行继续操作符 作用:当定义的宏不能用一行表达完整时,可以用”\”表示下一行继续此宏的定义。注意:换行不能切断单词,只能在空格的地方进行。
3.使用宏定义定义方法
/** 添加一个函数声明 */
#define _DEFINE_DATA_FUNC_INTERNAL(name, dataType) \
-(void)set##name:(dataType)value; \
-(dataType)get##name; \
+(NSString *)key##name; \
-(BOOL)has##name;
4.使用宏定义定义方法实现
/** 添加一个函数定义 */
#define _IMPLEMENT_DATA_FUNC_INTERNAL(name, dataType, funForType, strKey) \
-(void)set##name:(dataType)value { \
[self set##funForType:value forKey:strKey]; \
} \
-(dataType)get##name { \
return [self get##funForType:strKey]; \
} \
+(NSString *)key##name { \
return strKey; \
}\
-(BOOL)has##name {\
return [self hasKey:strKey]; \
}
5.使用宏定义创建单例类
#define GTMOBJECT_SINGLETON_BOILERPLATE(_object_name_, _shared_obj_name_) \
__strong static _object_name_ *z##_shared_obj_name_ = nil; \
+ (_object_name_ *)_shared_obj_name_ { \
static dispatch_once_t pred = 0; \
dispatch_once(&pred, ^{ \
z##_shared_obj_name_ = [[self alloc] init]; \
}); \
return z##_shared_obj_name_; \
} \
+ (id)allocWithZone:(NSZone *)zone { \
@synchronized(self) { \
if (z##_shared_obj_name_ == nil) { \
z##_shared_obj_name_ = [super allocWithZone:zone];\
} \
} \
return z##_shared_obj_name_; \
} \
- (id)copyWithZone:(NSZone *)zone { \
return self; \
} \
+ (void)destroy##_object_name_ { \
}