筆記-iOS預處理

預處理

程序中的源代碼計算機是沒法識別的,須要將寫好的代碼轉成0、1二進制代碼,計算機才能識別。將源代碼轉成二進制代碼須要兩步:編譯和連接編程

編譯是經過編譯器將每一個文件的代碼都轉爲二進制代碼,在這個過程當中,若是有語法錯誤,會有編譯失敗的提示,若是成功,那麼會生成對應多個目標文件。在一個文件中可能會用到其餘文件,所以,還須要將編譯生成的目標文件和系統提供的文件組合到一塊兒,這個過程就是連接,最後生成了可執行文件。
一般人們所理解的程序運行就是編譯和連接兩個階段,但實際上在編譯以前,預處理器要進行預處理操做,處理完以後才能進入到編譯階段。由於預處理指令是在編譯以前就進行了,因此它比程序運行時進行操做的效率高。bash

預處理程序其實是在分析程序前先處理的語句,它能夠識別散佈在程序中的特定語句。全部的預處理語句都適用"#"開頭,這個符號必須是一行中的第一個非空字符。函數

預處理能夠大概分爲三類:文件包含、宏定義和條件編譯ui

文件包含

文件包含:在當前文件中用到其它文件中的函數或方法或其它信息時,能夠將其它文件的頭文件包含進來,而後再當前文件中使用,文件包含通常放到文件的開頭。spa

若是使用C語言編程,文件包含是#include<>或者#include""。若是使用Objective-C語言,文件包含爲#import<>或者#import""#include#import最大的區別是:#import在導入文件的時候進行了去重複檢查,此外,""和<>二者也是有區別的,""通常是用來引用自定義的文件,<>通常是用來引用系統的文件。程序在執行的時候,會根據你寫的樣式,優先去尋找對應類型的文件。好比<>會先去找系統文件,若是找不到,再去找自定義文件。因此正確的選擇樣式,可以提升程序的執行效率。code

循環引用:在使用文件包含的時候,會遇到A文件中用到B文件,B文件中用到A文件,這種互相使用包含的關係就有點相似死循環了,運行的時候就會報錯。解決這個問題最好的辦法就是用@Class代替文件包含,@Class就是代表有這個類,等在源文件中真正用到的時候纔會去包含文件。get

宏定義

在程序中,有一些常量或者簡短的函數會被屢次重複調用的,對於這些經常使用的數據,咱們可使用宏定義。使用宏定義能夠快速的完成程序中的多處配置,最大的好處就是隻要修改宏定義的值,全部使用宏定義的值都會發生改變。此外,宏定義是在程序編譯以前進行替換和設置,比定義成全局變量或者函數的效率要高編譯器

宏定義是經過 #define來實現的,通常寫在程序文件包含的下面。宏名一般用所有的大寫字母表示。string

條件編譯

條件編譯:在編譯以前由預處理器來根據處理語句進行判斷,若是知足條件,就編譯知足條件下的代碼。反之就不進入編譯環節。
條件編譯主要分爲兩種:一種是判斷是否認義過某個宏,根據是否認義過這個宏,來決定是否編譯某段代碼。另外,還有一組語句和條件結構中的階梯if結構很是相似,可是寫法上有區別,是 #if、#elif、#else、#endif組成。須要注意的是,不管哪一種,都要有 #endif結束標誌。此外,最重要的一點是: 條件編譯中的條件不能使用普通變量,通常會選擇使用宏定義。io

#import <Foundation/Foundation.h>
#define ZB_COUNT 10

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        #if defined(ZB_COUNT)
            NSLog(@"定義了 COUNT 這個宏");
        #endif
        
        #ifndef defined(ZB_MAX)
            NSLog(@"沒有定義 ZB_COUNT 這個宏")
        #endif
        
        #if ZB_COUNT== 1
            NSLog(@"ZB_COUNT=1");
        #elif ZB_COUNT==2
            NSLog(@"ZB_COUNT=2");
        #elif ZB_COUNT==3
            NSLog(@"ZB_COUNT=3");
        #else
            NSLog(@"ZB_COUNT=%i", ZB_COUNT);
        #endif
    }
    return 0;
}
複製代碼

最後補充一下預處理經常使用指令:

# 空指令,沒有任何效果
#include 包含一個源代碼文件
#define 定義宏
#undef 取消定義宏
#if 若是條件爲真,則編譯下面的代碼
#elif 若是前面的#if不爲真,則編譯下面的代碼
#endif 結束一個#if。。。#elif條件編譯塊
#ifdef 若是已經定義了某個宏,則編譯下面的代碼
#ifndef 若是沒有定義某個宏,則編譯下面的代碼
#error 中止編譯並顯示錯誤信息
複製代碼

原文

相關文章
相關標籤/搜索