1. 判斷設(shè)備
// 是否高清屏
#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;
//效果相當(dāng)于 double i=2*3.1415926*3;
//預(yù)處理命令可以定義任何符合格式的形式板乙,例如判斷年份是否閏年
#define IS_LEAP_YEAR year%4==0&&year%100!=0||year%400==0
//使用時(shí)則可以直接
if(IS_LEAP_YEAR)
//或者可以定義一個(gè)參數(shù)
#define IS_LEAP_YEAR(y) y%4==0&&y%100!=0||y%400==0
//使用時(shí)則可以直接
int ys=2012;
if(IS_LEAP_YEAR(ys))
//通常預(yù)處理程序定義在一行 如果好分行 比如說太長(zhǎng)需要換行 需要使用“/”符號(hào) 表示還有下一行步做,多行分列也是如此耳璧,例:
#Define IS_LEAP_YEAR year%4==0&&year%100!=0/
||year%400==0
//宏定義參數(shù)后邊放一個(gè)# 那么在調(diào)用該宏時(shí),預(yù)處理程序?qū)⒏鶕?jù)宏參數(shù)創(chuàng)建C風(fēng)格的常量字符串 例:
#define STR(x) # x
//將會(huì)使得 隨后調(diào)用的
NSLOG(STR(Programming in Objective-c./n));
//顯示結(jié)果為 Programming in Objective-c./n
3. 關(guān)于#與##的操作符
- 宏定義中字符串操作符#:
#的功能是將其后面的宏參數(shù)進(jìn)行字符串化操作键袱,意思就是對(duì)它所應(yīng)用的宏變量通過替換后在其左右各加上一個(gè)雙引號(hào)护桦。例如
#define WARN_IF(EXPR)\
do {\
if (EXPR)\
fprintf(stderr, "Warning: " #EXPR "\n");\
} while(0)
上面代碼中的反斜線\主要用來(lái)轉(zhuǎn)譯換行符,即屏蔽換行符矾瘾。
那么如下的代碼調(diào)用:
WARN_IF(divider == 0);
將被解析為:
do {\
if (divider == 0)\
fprintf(stderr, "Warning: " "divider == 0" "\n");\
} while(0);
- 宏定義中的連接符##:
連接符##用來(lái)將兩個(gè)token連接為一個(gè)token,但它不可以位于第一個(gè)token之前or最后一個(gè)token之后箭启。注意這里連接的對(duì)象只要是token就行壕翩,而不一定是宏參數(shù),但是##又必須位于宏定義中才有效,因其為編譯期概念(比較繞)册烈。
#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;
如下調(diào)用宏:
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將報(bào)錯(cuò)婿禽!
正確的寫法為:
#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語(yǔ)言的預(yù)處理命令簡(jiǎn)介:
define 定義一個(gè)預(yù)處理宏
undef 取消宏的定義
include 包含文件命令
include_next 與#include相似, 但它有著特殊的用途
if 編譯預(yù)處理中的條件命令, 相當(dāng)于C語(yǔ)法中的if語(yǔ)句
ifdef 判斷某個(gè)宏是否被定義, 若已定義, 執(zhí)行隨后的語(yǔ)句
ifndef 與#ifdef相反, 判斷某個(gè)宏是否未被定義
elif 若#if, #ifdef, #ifndef或前面的#elif條件不滿足, 則執(zhí)行#elif之后的語(yǔ)句, 相當(dāng)于C語(yǔ)法中的else-if
else 與#if, #ifdef, #ifndef對(duì)應(yīng), 若這些條件不滿足, 則執(zhí)行#else之后的語(yǔ)句, 相當(dāng)于C語(yǔ)法中的else
endif #if, #ifdef, #ifndef這些條件命令的結(jié)束標(biāo)志.
defined 與#if, #elif配合使用, 判斷某個(gè)宏是否被定義
line 標(biāo)志該語(yǔ)句所在的行號(hào)
將宏參數(shù)替代為以參數(shù)值為內(nèi)容的字符竄常量
將兩個(gè)相鄰的標(biāo)記(token)連接為一個(gè)單獨(dú)的標(biāo)記
pragma 說明編譯器信息#warning 顯示編譯警告信息
error 顯示編譯錯(cuò)誤信息
參考鏈接:http://www.uml.org.cn/c++/200902104.asp