Objective-C 宏定义

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&&year%100!=0||year%400==0    
//使用时则可以直接    
if(IS_LEAP_YEAR)    
   
//或者可以定义一个参数      
#define  IS_LEAP_YEAR(y)  y%4==0&&y%100!=0||y%400==0    
//使用时则可以直接     
int ys=2012;     
if(IS_LEAP_YEAR(ys))       
    
//通常预处理程序定义在一行 如果好分行 比如说太长需要换行  需要使用“/”符号 表示还有下一行,多行分列也是如此,例:    
#Define  IS_LEAP_YEAR  year%4==0&&year%100!=0/    
           ||year%400==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连接为一个token,但它不可以位于第一个token之前or最后一个token之后。注意这里连接的对象只要是token就行,而不一定是宏参数,但是##又必须位于宏定义中才有效,因其为编译期概念(比较绕)。
#define LINK_MULTIPLE(a, b, c, d) a##_##b##_##c##_##d  
typedef struct _record_type LINK_MULTIPLE(name, company, position, salary);  
/*  
* 上面的代码将被替换为  
* typedef struct _record_type name_company_position_salary;  
*/  
  
又如下面的例子:  
#define PARSER(N) printf("token" #N " = %d\n", token##N)  
  
int token64 = 64;  
  
如下调用宏:  
PARSER(64);  
  
将被解析为:  
printf("token" "64" " = %d\n", 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. 宏定义 Objective-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) {              
/* Note that ‘self’ may not be the same as _object_name_ */                                
/* first assignment done in allocWithZone but we must reassign in case init fails */       
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_;                  
}                                               
}                                                 
   
/* We can’t return the shared instance, because it’s been init’d */  
_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. 条件编译
```ObjC
#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 显示编译错误信息

参考链接:http://www.uml.org.cn/c++/200902104.asp
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容