IOS 預先處理語句,ios預先處理語句
程式中的原始碼電腦是無法識別的,需要將寫好的代碼轉成0、1二進位代碼,電腦才能識別。將原始碼轉成二進位代碼的需要經過兩步,編譯和連結。編譯是通過編譯器將每個檔案的代碼都轉為二進位代碼,在這個過程中,如果有語法錯誤,會有編譯失敗的提示,如果成功,那麼會產生對應多個目標檔案。在一個檔案中可能會用到其他檔案,因此,還需要將編譯產生的目標檔案和系統提供的檔案組合到一起,這個過程就是連結。經過連結,最後產生了可執行檔。
通常人們所理解的程式運行就是編譯和連結兩個階段,但實際上在編譯之前前置處理器要進行預先處理操作,處理完之後才進入到編譯階段。因為預先處理指令是在編譯之前就行進了,所以它比程式運行時進行操作的效率高。
預先處理程式實際上是在剖析器前先處理的語句,它可以識別散步在程式中的特定語句。所有的預先處理語句都使用井號(#)開頭,這個符號必須是一行中的第一個非Null 字元。
預先處理語句可以大概劃分成三類:檔案包含、宏定義和條件編譯,下面,就一一來講解。
檔案包含
檔案包含指的是在當前檔案中用到其他檔案中的函數或方法或者是其他資訊時,可以將其他檔案的標頭檔包含進來,然後再當前檔案中使用,檔案包含一般放到檔案的開頭位置。
如果使用C語言編程,檔案包含是#include<> 或者 #include“”。如果使用Objective-C語言,檔案包含為#import<>或者#import“”。#include與#import最大的區別是#import在匯入檔案的時候進行了去重複檢查。此外,“”和<>兩個也是有區別的,“”是用來放自己寫的檔案,<>用來放系統檔案。程式在執行的時候,會根據你寫的樣式,優先去尋找對應類型的檔案。比如<>,會先去找系統的檔案,如果找不到,再去找自訂的檔案。所以,正確的選擇樣式,能夠提高程式的運行效率。
在使用檔案包含的時候,會遇到A檔案中用到B檔案,B檔案中用到A檔案,這種相互使用包含的關係,這種情況就有點像死迴圈了,要使用A檔案,必須要先有B,可是在B中,又需要先有A,因此在啟動並執行時候,會出現錯誤。解決這個問題最好的辦法,是用@class代替檔案包含,@class就是表明有這個類,等在源檔案中真正用到的時候再包含檔案。
代碼:
// A.h// Test//// Created by jerei on 15-7-24.// Copyright (c) 2015年 jerehedu. All rights reserved.//#import <Foundation/Foundation.h>@class B;@interface A : NSObject@property (nonatomic, strong) B *obj;@end//// B.h// Test//// Created by jerei on 15-7-24.// Copyright (c) 2015年 jerehedu. All rights reserved.//#import <Foundation/Foundation.h>@class A;@interface B : NSObject@property (nonatomic, strong) A *obj;@end
宏定義
在程式中,有一些常量或者簡短的函數是會多次重複使用的,對於這些常用的資料,我們可以使用宏定義。使用宏定義可以快速的完成程式中多處的配置,最大的好處是只要修改宏定義的值,所有使用宏定義的值都會發生改變。此外,宏定義是在程式編譯之前進行替換和設定,比定義成全域變數或函數的效率要高。
宏定義是通過#define來實現的,一般寫在程式的檔案包含的下面。宏名通常用全部的大寫字母表示。下面,就通過代碼舉來看一下宏定義的使用。
代碼:
// main.m// Test//// Created by jerei on 15-7-24.// Copyright (c) 2015年 jerehedu. All rights reserved.//#import <Foundation/Foundation.h>#define JR_PI 3.14#define JR_MAX(a,b) ((a>b)?(a):(b)) //得到兩個數中較大值#define JR_SQUARE_1(n) n*n //求數位平方#define JR_SQUARE_2(n) (n)*(n) //求數位平方#define JR_HELLO @"hello world";int main(int argc, const char * argv[]) { @autoreleasepool { int num1 = JR_MAX(1, 2); NSLog(@"max = %i",num1); //結果: max = 2 int num2 = JR_SQUARE_1(2); NSLog(@"2的平方 = %i",num2); //結果:2的平方 = 4 int num3 = JR_SQUARE_1(2+1); NSLog(@"(2+1)的平方 = %i",num3); //結果:(2+1)的平方 = 5 int num4 = JR_SQUARE_2(2+1); NSLog(@"(2+1)的平方 = %i",num4); //結果:(2+1)的平方 = 9 } return 0;}
在代碼中可以看到,同樣都是求一個數的平方,但是兩個宏定義得到的結果卻是不一樣的。第一個計算2+1的平方的時候是2+1*2+1,所以結果為5,答案錯誤。因此,在寫宏定義,帶參數的時候,需要設定小括弧,保證正確性。
條件編譯
條件編譯其實就在編譯之前由前置處理器來根據預先處理語句進行判斷,如果滿足條件,就編譯滿足條件下面的程式碼片段,如果不滿足條件,下面的程式碼片段就不進入編譯環節。
條件編譯主要分為兩種,一種是判斷是否定義過某個宏,根據是否定義過這個宏,來決定是否編譯某段代碼。另外,還有一組語句和條件結構中的階梯if結構非常類似,但是寫法上有所區別,是#if、#elif、#else、#endif組成。需要注意的是,無論哪種,都要有#endif結束標誌。此外,最重要的一點是,條件編譯中的條件不能使用普通的變數,一般會選擇使用宏定義。
代碼:
// main.m// Test//// Created by jerei on 15-7-24.// Copyright (c) 2015年 jerehedu. All rights reserved.//#import <Foundation/Foundation.h>#define JR_COUNT 10int main(int argc, const char * argv[]) { @autoreleasepool { #if defined(JR_COUNT) NSLog(@"定義了 COUNT 這個宏");#endif #if defined(JR_MAX) NSLog(@"沒有定義了 JR_MAX 這個宏");#endif #if JR_COUNT==1 NSLog(@"JR_COUNT=1");#elif JR_COUNT==2 NSLog(@"JR_COUNT=2");#elif JR_COUNT==3 NSLog(@"JR_COUNT=3");#else NSLog(@"JR_COUNT=%i",JR_COUNT);#endif } return 0;}
疑問諮詢或技術交流,請加入官方QQ群: (452379712)
作者:傑瑞教育
出處:http://www.cnblogs.com/jerehedu/
本文著作權歸煙台傑瑞教育科技有限公司和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則保留追究法律責任的權利。