1、先来几个常用的:
// 是否高清屏
#define isRetina ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) : NO)
// 是否模拟器
#define isSimulator (NSNotFound != [[[UIDevice currentDevice] model] rangeOfString:@"Simulator"].location)
// 是否iPad
#define isPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
// 是否iPad
#define someThing (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)? ipad: iphone
2、基本的使用:
//定义π值 3.1415926
#define PI 3.1415926
//则在程序用可以如下使用
double i=2*PI*3;
//效果相当于 double i=2*3.1415926*3;
//预处理命令可以定义任何符合格式的形式,例如判断年份是否闰年
#define IS_LEAP_YEAR year%4==0&&year0!=0||year@0==0
//使用时则可以直接
if(IS_LEAP_YEAR)
//或者可以定义一个参数
#define IS_LEAP_YEAR(y) y%4==0&&y0!=0||y@0==0
//使用时则可以直接
int ys=2012;
if(IS_LEAP_YEAR(ys))
//通常预处理程序定义在一行 如果好分行 比如说太长需要换行 需要使用“/”符号 表示还有下一行,多行分列也是如此,例:
#Define IS_LEAP_YEAR year%4==0&&year0!=0/
||year@0==0
//宏定义参数后边放一个# 那么在调用该宏时,预处理程序将根据宏参数创建C风格的常量字符串 例:
#define STR(x) # x
//将会使得 随后调用的
NSLOG(STR(Programming in Objective-c./n));
//显示结果为 Programming in Objective-c./n
3、关于#与##的操作符:
#define WARN_IF(EXPR)
do {
if (EXPR)
fprintf(stderr, "Warning: " #EXPR "n");
} while(0)
上面代码中的反斜线主要用来转译换行符,即屏蔽换行符。
那么如下的代码调用:
WARN_IF(divider == 0);
将被解析为:
do {
if (divider == 0)
fprintf(stderr, "Warning: " "divider == 0" "n");
} while(0);
注意能够字符串化操作的必须是宏参数,不是随随便便的某个子串(token)都行的。
#define LINK_MULTIPLE(a, b, c, d) a##_##b##_##c##_##d
typedef struct _record_type LINK_MULTIPLE(name, company, position, salary);
又如下面的例子:
#define PARSER(N) printf("token" #N " = %dn", token##N)
int token64 = 64;
如下调用宏:
PARSER(64);
将被解析为:
printf("token" "64" " = %dn", token64);
在obj-c中,如果我有如下定义:
#define _X(A, B) (A#B)
#define _XX(A, B) _X([NSString stringWithFormat:@"%@_c", A], B)
gcc将报错!
正确的写法为:
#define _XX(A, B) _X(([NSString stringWithFormat:@"%@_c", A]), B)
4、再来个宏定义 object-c 单例
#define GTMOBJECT_SINGLETON_BOILERPLATE(_object_name_, _shared_obj_name_)
static _object_name_ *z##_shared_obj_name_ = nil;
+ (_object_name_ *)_shared_obj_name_ {
@synchronized(self) {
if (z##_shared_obj_name_ == nil) {
z##_shared_obj_name_ = [[self alloc] init];
_GTMDevAssert((z##_shared_obj_name_ != nil), @”didn’t catch singleton allocation”);
}
}
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_;
}
}
_GTMDevAssert(NO, @”use the singleton API, not alloc+init”);
return nil;
}
- (id)retain {
return self;
}
- (NSUInteger)retainCount {
return NSUIntegerMax;
}
- (void)release {
}
- (id)autorelease {
return self;
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
5、条件编译:
#if !defined(FCDebug) || FCDebug == 0
#define FCLOG(...) do {} while (0)
#define FCLOGINFO(...) do {} while (0)
#define FCLOGERROR(...) do {} while (0)
#elif FCDebug == 1
#define FCLOG(...) NSLog(__VA_ARGS__)
#define FCLOGERROR(...) NSLog(__VA_ARGS__)
#define FCLOGINFO(...) do {} while (0)
#elif FCDebug > 1
#define FCLOG(...) NSLog(__VA_ARGS__)
#define FCLOGERROR(...) NSLog(__VA_ARGS__)
#define FCLOGINFO(...) NSLog(__VA_ARGS__)
#endif
6、参照C语言的预处理命令简介 :
#define 定义一个预处理宏
#undef 取消宏的定义
#include 包含文件命令
#include_next 与#include相似, 但它有着特殊的用途
#if 编译预处理中的条件命令, 相当于C语法中的if语句
#ifdef 判断某个宏是否被定义, 若已定义, 执行随后的语句
#ifndef 与#ifdef相反, 判断某个宏是否未被定义
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
defined 与#if, #elif配合使用, 判断某个宏是否被定义
#line 标志该语句所在的行号
# 将宏参数替代为以参数值为内容的字符窜常量
## 将两个相邻的标记(token)连接为一个单独的标记
#pragma 说明编译器信息#warning 显示编译警告信息
#error 显示编译错误信息