iOS - 條件編譯

圖片源于網(wǎng)絡(luò)

1.預(yù)處理指令

  • 1)C語(yǔ)言在對(duì)源程序進(jìn)行編譯之前,會(huì)先對(duì)一些特殊的預(yù)處理指令作解釋。預(yù)處理過(guò)程掃描源代碼,對(duì)其進(jìn)行初步的轉(zhuǎn)換,產(chǎn)生新的源代碼提供給編譯器。

  • 2)預(yù)處理指令是以#號(hào)開(kāi)頭的代碼行。#號(hào)必須是該行除了任何空白字符外的第一個(gè)字符。#后是指令關(guān)鍵字,在關(guān)鍵字和#號(hào)之間允許存在任意個(gè)數(shù)的空白字符。整行語(yǔ)句構(gòu)成了一條預(yù)處理指令,該指令將在編譯器進(jìn)行編譯之前對(duì)源代碼做某些轉(zhuǎn)換。

  • 3)預(yù)處理指令可以放在文件任何位置,他的作用范圍是從它出現(xiàn)的位置到文件尾,習(xí)慣上我們常把它放在源程序頭部,這樣它的作用范圍就是整個(gè)源程序文件了

  • 4)預(yù)處理指令可分成三類:宏定義、文件包含、條件編譯

2.宏定義

  • 1)宏定義了一個(gè)代表特定內(nèi)容的標(biāo)識(shí)符。預(yù)處理過(guò)程會(huì)把源代碼中出現(xiàn)的宏標(biāo)識(shí)符替換成宏定義時(shí)的值。

  • 2)#define指令: 不帶參數(shù)的宏定義(宏名一般大寫

    • 一般形式:#define 宏名 字符串
    #define COUNT 5
    
    • 宏表示的值可以是一個(gè)常量表達(dá)式,其中允許包括前面已經(jīng)定義的宏標(biāo)識(shí)符。
    #define ONE1 1
    #define TWO2 2
    #define THREE (ONE+TWO)
    

    注意上面的宏定義使用了括號(hào)。盡管它們并不是必須的。但出于謹(jǐn)慎考慮,還是應(yīng)該加上括號(hào)的。

    NSInteger six = 0;
    six = THREE * TWO;
    //預(yù)處理過(guò)程把上面的一行代碼轉(zhuǎn)換成:
    six = (ONE+TWO) * TWO;
    //如果沒(méi)有那個(gè)括號(hào),就轉(zhuǎn)換成
    six = ONE+TWO * TWO;
    
    • 宏還可以代表一個(gè)字符串常量
    #define VERSION "Version1.0 Copyright(c)2003"
    
  • 3)帶參數(shù)的#define指令:帶參數(shù)的宏定義(宏名一般大寫

    • 一般形式:#define 宏名 (參數(shù))
    #define Cube (x)  (x)*(x)*(x)
    
    • 帶參數(shù)的宏和函數(shù)調(diào)用看起來(lái)有些相似。可以是任何數(shù)字表達(dá)式甚至函數(shù)調(diào)用來(lái)代替參數(shù)x。這里再次提醒大家注意括號(hào)的使用。宏展開(kāi)后完全包含在一對(duì)括號(hào)中,而且參數(shù)也包含在括號(hào)中,這樣就保證了宏和參數(shù)的完整性。
    NSInteger volume = 0;
    int num = 8+2;
    volume = Cube(num);
    //展開(kāi)后為(8+2)*(8+2)*(8+2)
    //如果沒(méi)有那些括號(hào)就變?yōu)?+2*8+2*8+2
    
    • 帶參數(shù)的宏比函數(shù)效率高,宏只會(huì)替換數(shù)值(文本對(duì)換)。不計(jì)算,不會(huì)替換雙引號(hào)括住的字符串。

    • 把可能產(chǎn)生副作用的操作移到宏調(diào)用的外面進(jìn)行

    NSInteger volume = 0;
    int num = 8+2;
    volume = Cube(num++);//不安全的用法
    /**展開(kāi)后是這樣的:
      volume=(num++)*(num++)*(num++);
      很顯然,結(jié)果是10*11*12,而不是10*10*10;
    */
    volume = Cube(num);//安全的用法
    num++;
    
  • 4)#運(yùn)算符

    • 出現(xiàn)在宏定義中的#運(yùn)算符把跟在其后的參數(shù)轉(zhuǎn)換成一個(gè)字符串。有時(shí)把這種用法的#稱為字符串化運(yùn)算符
    #define PASTE (n) "hello  "#n
    main()
    {
      NSLog(@"%@",PASTE(2018));
      //宏定義中的#運(yùn)算符告訴預(yù)處理程序,把源代碼中任何傳遞給該宏的參數(shù)轉(zhuǎn)換成一個(gè)字符串。所以輸出應(yīng)該是hello  2018
    }
    
  • 5)##運(yùn)算符

    • ## 運(yùn)算符用于把參數(shù)連接到一起。預(yù)處理程序把出現(xiàn)在##兩側(cè)的參數(shù)合并成一個(gè)符號(hào)。
    #define NUM (a,b,c) a##b##c
    #define STR (a,b,c) a##b##c
    
    main()
    {
      NSLog("%ld ",NUM(1,2,3));
      NSLog("%@ ",STR("aa","bb","cc"));
    //輸出結(jié)果為123  aabbcc
    }
    
    • 除非需要或者宏的用法恰好和手頭的工作相關(guān),否則很少有程序員會(huì)知道##運(yùn)算符。絕大多數(shù)程序員從來(lái)沒(méi)用過(guò)它。

3.條件編譯指令

  • 條件編譯指令將決定那些代碼被編譯,而哪些是不被編譯的??梢愿鶕?jù)表達(dá)式的值或者某個(gè)特定的宏是否被定義來(lái)確定編譯條件。
  • 預(yù)編譯指令中的表達(dá)式與C語(yǔ)言本身的表達(dá)式基本一至.如邏輯運(yùn)算、算術(shù)運(yùn)算、位運(yùn)算等均可以在預(yù)編譯指令中使用。
  • 之所以能夠?qū)崿F(xiàn)條件編譯是因?yàn)轭A(yù)編譯指令是在編譯之前進(jìn)行處理的,通過(guò)預(yù)編譯進(jìn)行宏替換、條件選擇代碼段,然后生成最后的待編譯代碼,最后進(jìn)行編譯。
指令用途
#空指令,無(wú)任何效果
#include包含一個(gè)源代碼文件
#define定義宏
#undef取消已定義的宏
#if如果給定條件為真,則編譯下面代碼
#ifdef如果宏已經(jīng)定義,則編譯下面代碼
#ifndef如果宏沒(méi)有定義,則編譯下面代碼
#elif如果前面的#if給定條件不為真,當(dāng)前條件為真,則編譯下面代碼
#endif結(jié)束一個(gè)#if……#else條件編譯塊
#error停止編譯并顯示錯(cuò)誤信息
編譯方法
  1. #if ... #elif ... #else ... #endif
#if 條件 1
 代碼段 1
#elif 條件 2
 代碼段 2
...
#elif 條件 n
 代碼段 n
#else
 代碼段 n+1
#endif
  • #if的一般含義是,如果#if后面的常量表達(dá)式為true,則編譯它所控制的代碼.

  • 如果條件1成立時(shí)就代碼段1,條件1不成立再看條件2是否成立;如果條件2成立則編譯代碼段2,否則再依次類推判斷其它條件;如果條件1-N都不成力則會(huì)編譯最后的代碼段n+1.

  • 務(wù)必不能忘了#endif

  1. #ifdef ... #else ... #endif#ifndef ... #else ... #endif
#ifdef macro_name
    代碼段 1
#else
    代碼段 2
#endif

#ifndef macro_name
    代碼段 1
#else
    代碼段 2
#endif
  • #ifdef指令與#ifndef指令,它們分別表示“如果有定義”及“如果無(wú)定義”。

  • 有定義是指在編譯此段代碼時(shí)是否有某個(gè)宏通過(guò) #define指令定義的宏,#ifndef指令指找不到通過(guò)#define定義的某宏

  • 該宏可以是在當(dāng)前文件此條指令的關(guān)面定義的,也可以是在其它文件中,但在此指令之前包含到該文件中的。

  • #ifdef指令與#if defined()用法一致

    #if defined (宏)
       代碼.
    #endif
    
    • 這個(gè)#if后面接的是一個(gè)宏,意思是前面的宏定義里面有沒(méi)有定義這個(gè)宏,如果定義了,編譯器就會(huì)編譯中間的代碼,如果沒(méi)有定義,那就不會(huì)編譯,不管這個(gè)宏定義的是什么東西,對(duì)不對(duì)等
  • #ifndef指令與if !defined()用法一致(取反的意思

3、defined(macro_name)

  • 參數(shù)為宏名(無(wú)需加""),如果該macro_name定義過(guò)則返回真,否則返回假

  • 用該函數(shù)則可以寫比較復(fù)雜的條件編譯指令

#if defined(macro1) || (!defined(macro2) && defined(macro3))
...
#else
...
#endif

參考

ios筆記--宏定義,條件編譯和文件導(dǎo)入筆記

C語(yǔ)言的條件編譯#if, #elif, #else, #endif、#ifdef, #ifndef

Objective--C語(yǔ)言預(yù)處理命令之條件編譯(#ifdef,#else,#endif,#if等)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容