iOS預(yù)編譯指令詳解

1.預(yù)處理的概念

ANSI C標(biāo)準(zhǔn)(ANSI C是美國國家標(biāo)準(zhǔn)協(xié)會(ANSI)對C語言發(fā)布的標(biāo)準(zhǔn))規(guī)定可以在C源程序中加入一些“預(yù)處理命令” ,以改進(jìn)程序設(shè)計(jì)環(huán)境藤树,提高編程效率。這些預(yù)處理命令是由ANSI C統(tǒng)一規(guī)定的,但是它不是C語言本身的組成部分闻妓,不能直接對它們進(jìn)行編譯,因?yàn)榫幾g程序不能識別它們掠械,必須在對程序進(jìn)行通常的編譯之前由缆,先對程序中這些特殊的命令進(jìn)行處理,這一過程就是我們說的“預(yù)處理”猾蒂。經(jīng)過預(yù)處理后程序可由編譯程序?qū)︻A(yù)處理后的源程序進(jìn)行通常的編譯均唉,得到可供執(zhí)行的目標(biāo)代碼。

2.預(yù)處理指令功能

在C語言中包括三類預(yù)處理指令:1.宏定義 2.條件編譯 3.文件包含婚夫。

宏定義:

(1)宏的定義

定義格式: #define 標(biāo)識符 字符串
1浸卦、 不含參數(shù): #define TAG_VIEW 10086
2、 含有參數(shù):#define MAX_INT(a,b) a+b

(2)宏定義的說明

1案糙、宏名一般習(xí)慣用大寫字母表示限嫌,以便與變量名相區(qū)別。但這并非規(guī)定时捌,也可用小寫字母怒医。
2、 宏定義是用宏名代替一個(gè)字符串奢讨,只作簡單置換稚叹,不作正確性檢查,同時(shí)也不會做運(yùn)算邏輯處理,同時(shí)在進(jìn)行宏定義時(shí)拿诸,可以引用已定義的宏名扒袖,可以層層置換。(在這里需要特別注意的是:當(dāng)宏涉運(yùn)算時(shí)亩码,要根據(jù)情況來添加括號季率,防止運(yùn)算邏輯出現(xiàn)錯(cuò)誤,如下圖所示描沟,當(dāng)你宏MAX_TXT想作為整體來使用時(shí)應(yīng)該寫成這樣: #define MAX_INT (2+3) 這樣MAX_END的結(jié)果應(yīng)該是25飒泻,如果不加括號,只會進(jìn)行置換行為吏廉,MAX_END的結(jié)果就為11泞遗。在這非常感謝 @星星月亮落一地 的提醒)


3、 宏定義不是C語句席覆,不必在行末加分號史辙。如果加了分號則會連分號一起進(jìn)行置換。
4、 #define 命令出現(xiàn)在程序中函數(shù)的外面髓霞,宏名的有效范圍為定義命令之后到本文件結(jié)束卦睹。通常,#define 命令寫在文件開頭方库,函數(shù)之前结序,作為文件一部分,在此文件范圍內(nèi)有效纵潦。
5徐鹤、 可以用
#undef
命令終止宏定義的作用域。

6邀层、對程序中用雙撇號括起來的字符串內(nèi)的字符返敬,即使與宏名相同,也不進(jìn)行置換寥院。NSLog(@"MAX_INT = %d", 10086)
7劲赠、宏定義是專門用于預(yù)處理命令的一個(gè)專用名詞,它與定義變量的含義不同秸谢,只作字符替換凛澎,不分配內(nèi)存空間。

條件編譯:

條件編譯就是在編譯之前預(yù)處理器根據(jù)預(yù)處理指令判斷對應(yīng)的條件估蹄,如果條件滿足就將對應(yīng)的代碼編譯進(jìn)去塑煎,否則代碼就根本不進(jìn)入編譯環(huán)節(jié)(相當(dāng)于根本就沒有這段代碼)。

常用條件編譯函數(shù)

1臭蚁、#if 編譯預(yù)處理中的條件命令, 相當(dāng)于C語法中的if語句
2最铁、#ifdef 判斷某個(gè)宏是否被定義, 若已定義, 執(zhí)行隨后的語句
3、#ifndef 與#ifdef相反, 判斷某個(gè)宏是否未被定義
4垮兑、#elif 若#if, #ifdef, #ifndef或前面的#elif條件不滿足, 則執(zhí)行#elif之后的語句, 相當(dāng)于C語法中的else-if
6冷尉、#else 與#if, #ifdef, #ifndef對應(yīng), 若這些條件不滿足, 則執(zhí)行#else之后的語句, 相當(dāng)于C語法中的else
7、#endif #if, #ifdef, #ifndef這些條件命令的結(jié)束標(biāo)志.
8系枪、#if 與 #ifdef 的區(qū)別:#if是判斷后面的條件語句是否成立网严,#ifdef是判斷某個(gè)宏是否被定義過。要區(qū)分開嗤无!

#ifdef  MAX_F
// 如果定義了宏MAX_F,則編譯此處的代碼
#else
// 如果沒有定義宏MAX_F怜庸,則編譯此處的代碼
#endif

// 同樣
#ifndef  MAX_F
// 如果沒有定義宏MAX_F当犯,則編譯此處的代碼
#elif MAX_INT
// 如果定義了宏MAX_F,同時(shí)還定義了宏MAX_INT,則編譯此處的代碼
#else
// 定義了宏MAX_F,但是沒有定義宏MAX_INT割疾,則編譯此處的代碼
#endif

另外,在創(chuàng)建一個(gè)頭文件或pch文件 --- 單獨(dú)的一個(gè).h文件時(shí)嚎卫,常看到文件內(nèi)自帶了下述格式內(nèi)容

#ifndef Header_h 
#define Header_h 

#endif

上面的格式是為了防止該頭文件被引用時(shí)發(fā)生重復(fù)引用。

文件包含:

C語言下一般使用 #include, OC中一般使用#import ,它們的區(qū)別是:在使用#include的時(shí)候要注意處理重復(fù)引用拓诸,#import大部分功能和#include是一樣的,但是他處理了重復(fù)引用的問題,我們在引用文件的時(shí)候不用再去自己進(jìn)行重復(fù)引用處理侵佃。OC中還有一個(gè)引用聲明 @class主要是用于聲明一個(gè)類,告訴編譯器它后面的名字是一個(gè)類的名字,而這個(gè)類的定義實(shí)現(xiàn)是暫時(shí)不用知道的。一般來說,在interface中(.h文件)引用一個(gè)類,就用@class,它會把這個(gè)類作為一個(gè)類型來使用,而在實(shí)現(xiàn)這個(gè)interface的文件中,如果需要引用這個(gè)類的實(shí)體變量或者方法之類的,還是需要import這個(gè)在@class中聲明的類奠支。

3.關(guān)于宏的靈活使用和拓展:

1馋辈、在宏中拼接新的宏(限字符串)

(1)OC的代碼寫法:

#define aaa @"i am aaa"
#define bbb @"i am bbb"
#define  ccc @""bbb@" "aaa@""

打印ccc的結(jié)果如下


(2)C的寫法

#define aaa "i am aaa"
#define bbb "i am bbb"
#define  ccc ""bbb" "aaa""

打印結(jié)果是一樣的。

2倍谜、預(yù)處理連接符:#操作符的字符串化和 ##操作符

(1)在含參數(shù)宏中迈螟,假如希望在字符串中包含宏的參數(shù)本身,#符號用作一個(gè)預(yù)處理運(yùn)算符尔崔,它可以把語言符號轉(zhuǎn)化成字符串該過程稱為字符串化(stringizing)答毫。

//定義含參宏
#define MAX_TAG(maxTag) NSLog(@"the max tag "#maxTag" %d", maxTag *3)
-----------------------------------------------------------------------
// 調(diào)用
 MAX_TAG(33);
-----------------------------------------------------------------------
//打印結(jié)果為
2016-11-29 10:53:45.655 SpeachTest[2294:271425] the max tag 33 99

(2)# #操作符結(jié)合了兩種標(biāo)記成一個(gè)token,該標(biāo)記可以替代部分字符串。

 #define MMM(a)   a ## Button
--------------------------------------------------------------------
    NSString * MMM(title) = @"asd";
    NSLog(@"titleButton = %@",MMM(title));
    NSLog(@"titleButton = %@", titleButton);
--------------------------------------------------------------------
//打印的結(jié)果
2016-11-29 10:57:27.364 SpeachTest[2179:233773] titleButton = asd
2016-11-29 10:57:27.367 SpeachTest[2179:233773] titleButton = asd

在這里我并沒有直接定義“titleButton”季春,但是打印titleButton不但不報(bào)錯(cuò)而且titleButton已經(jīng)定義過了洗搂。 titleButton其實(shí)就是MMM(title),這就是##的作用载弄,大家可以試一下耘拇。

3、在宏定義中換行

只需要在每行的結(jié)尾添加反斜杠“\”

#define SHOWALERT(m)\
{\
    UIAlertView *alert  =  [[UIAlertView alloc]  initWithTitle:@" 提 示 "  message:m delegate:nil cancelButtonTitle:@"確認(rèn)" otherButtonTitles:nil];\
    [alert show];\
}\

4侦锯、 defined()函數(shù) 與 #if等條件條件編譯函數(shù)的應(yīng)用

#define aaa "i am aaa"
#if ( defined(aaa) && !defined(bbb) )
#define bbb "i am bbb"
#else
#define bbb "i am bbb_2"
#endif

打印bbb的結(jié)果:


5驼鞭、 省略號···和 VA_ARGS

關(guān)于省略號··· 代表的是個(gè)數(shù)可變的參數(shù)即可變參數(shù),一般會與__VA__ARGS__結(jié)合使用尺碰,__VA__ARGS__表示保留名挣棕,將省略號省略的參數(shù)傳遞給宏。

// 例如我們最常見的形式
#ifdef DEBUG
#define JRLog(...) NSLog(__VA_ARGS__)
#else
#define JRLog(...)// 如果編譯經(jīng)過在這里那么JRLog(···)無意義
#endif

還有當(dāng)含參數(shù)宏的參數(shù)至少有一個(gè)時(shí):

#ifdef DEBUG
#define JRLog(aaa, ...) NSLog(aaa, ##__VA_ARGS__)
#else
#define JRLog(...)
#endif

此時(shí)##的作用是在可變參數(shù)被忽略或?yàn)榭盏那闆r下亲桥,‘##’操作將使預(yù)處理器去除掉“···”前面的那個(gè)逗號洛心。

  • 特別注意:省略號···只能出現(xiàn)在參數(shù)的最后面,放在其他參數(shù)中間或者前面是不可以的题篷!

6词身、iOS常用的系統(tǒng)內(nèi)參數(shù)宏

// 判斷是否是真機(jī)
#if TARGET_OS_IPHONE // 在這里一定不能使用#ifdef,因?yàn)門ARGET_OS_IPHONE無論在真機(jī)還是模擬器情況下都存在只不過 模擬器時(shí)值為0
#else
#endif
// 判斷是否是模擬器
#if TARGET_OS_SIMULATOR // 同上番枚。"TARGET_IPHONE_SIMULATOR"已經(jīng)廢棄
#else
#endif
// 判斷手機(jī)系統(tǒng)版本
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0
#else
#endif
// 規(guī)定只能在ios系統(tǒng)下運(yùn)行
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED 
    // 規(guī)定運(yùn)行支持的最小版本
    #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
    #else
    #endif
#endif
// 可以參照Availability.h 文件  文件路徑 /Applications/Xcode8.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include 不同Xcode版本路徑略有差異
/**
 #define __IPHONE_2_0      20000
 #define __IPHONE_2_1      20100
 #define __IPHONE_2_2      20200
 #define __IPHONE_3_0      30000
 #define __IPHONE_3_1      30100
 #define __IPHONE_3_2      30200
 #define __IPHONE_4_0      40000
 #define __IPHONE_4_1      40100
 #define __IPHONE_4_2      40200
 #define __IPHONE_4_3      40300
 #define __IPHONE_5_0      50000
 #define __IPHONE_5_1      50100
 #define __IPHONE_6_0      60000
 #define __IPHONE_6_1      60100
 #define __IPHONE_7_0      70000
 #define __IPHONE_7_1      70100
 #define __IPHONE_8_0      80000
 #define __IPHONE_8_1      80100
 #define __IPHONE_8_2      80200
 #define __IPHONE_8_3      80300
 #define __IPHONE_8_4      80400
 #define __IPHONE_9_0      90000
 #define __IPHONE_9_1      90100
 #define __IPHONE_9_2      90200
 #define __IPHONE_9_3      90300
 #define __IPHONE_10_0    100000
 #define __IPHONE_10_1    100100
 */

開發(fā)常用的一些宏定義網(wǎng)上有很多法严,這里就不一一列舉了,希望對讀者有幫助葫笼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末深啤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子路星,更是在濱河造成了極大的恐慌溯街,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異呈昔,居然都是意外死亡挥等,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門堤尾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肝劲,“玉大人,你說我怎么就攤上這事哀峻∥邢啵” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵剩蟀,是天一觀的道長催蝗。 經(jīng)常有香客問我,道長育特,這世上最難降的妖魔是什么丙号? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮缰冤,結(jié)果婚禮上犬缨,老公的妹妹穿的比我還像新娘。我一直安慰自己棉浸,他們只是感情好怀薛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著迷郑,像睡著了一般枝恋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嗡害,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天焚碌,我揣著相機(jī)與錄音,去河邊找鬼霸妹。 笑死十电,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的叹螟。 我是一名探鬼主播鹃骂,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼罢绽!你這毒婦竟也來了偎漫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤有缆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棚壁,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杯矩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了袖外。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片史隆。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖曼验,靈堂內(nèi)的尸體忽然破棺而出泌射,到底是詐尸還是另有隱情,我是刑警寧澤鬓照,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布熔酷,位于F島的核電站,受9級特大地震影響豺裆,放射性物質(zhì)發(fā)生泄漏拒秘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一臭猜、第九天 我趴在偏房一處隱蔽的房頂上張望躺酒。 院中可真熱鬧,春花似錦蔑歌、人聲如沸羹应。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽园匹。三九已至,卻和暖如春帅矗,著一層夾襖步出監(jiān)牢的瞬間偎肃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工浑此, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留累颂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓凛俱,卻偏偏與公主長得像紊馏,于是被迫代替她去往敵國和親蒲犬。 傳聞我的和親對象是個(gè)殘疾皇子原叮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 目錄 一.預(yù)處理的工作方式... 3 1.1.預(yù)處理的功能... 3 1.2預(yù)處理的工作方式... 3 二.預(yù)處理...
    朱森閱讀 1,374評論 0 2
  • C中的預(yù)編譯宏定義 2009-02-10 作者: infobillows 來源:網(wǎng)絡(luò) 在將一個(gè)C源程序轉(zhuǎn)換為可執(zhí)行...
    白水灬煮一切閱讀 1,590評論 0 5
  • 在源代碼的編譯過程中,會需要一些機(jī)制來完成以下的一些功能:在編譯時(shí)包含其他源文件搬味、定義宏碰纬、根據(jù)條件決定編譯時(shí)是否包...
    趙亦晨閱讀 564評論 0 0
  • 文/孤鳥差魚 不要東拉西扯 別折磨打吊瓶的人
    孤鳥差魚閱讀 174評論 0 2
  • 今天你是否會想起,昨天學(xué)醫(yī)的你她按;明天你是否會惦記酌泰,這個(gè)溫暖的群體匕累!二十年之后的同學(xué)欢嘿,都已改變模樣炼蹦;雖然有各自的事業(yè)...
    關(guān)中刀客閱讀 223評論 0 0