iOS | 面試知識整理 - OC基礎 (一)

孤單的襯衣發表於2019-09-17

前言:

最近公司專案不怎麼忙, 閒暇時間把iOS 在面試中可能會遇到的問題整理了一番, 一部分題目是自己面試遇到的,一部分題目則是網上收錄的, 方便自己鞏固複習, 也分享給大家! 知識點比較多,比較雜,這裡做了分類,下面是分類連結地址;

面試知識點整理 - 目錄:
iOS | 面試知識整理 - OC基礎 (一)
iOS | 面試知識整理 - OC基礎 (二)
iOS | 面試知識整理 - OC基礎 (三)
iOS | 面試知識整理 - UI 相 關 (四)
iOS | 面試知識整理 - 記憶體管理 (五)
iOS | 面試知識整理 - 多 線 程 (六)
iOS | 面試知識整理 - 網路相關 (七)
iOS | 面試知識整理 - 資料持久化 (八)
iOS | 面試知識整理 - Swift 基礎 (九)

iOS | 面試知識整理 - OC基礎 (一)

1. #include、#import、@class的區別?

  • 在C 語言中, 我們使用 #include 來引入標頭檔案,如果需要防止重複匯入需要使用#ifndef...#define...#endif
  • 在OC語言中, 我們使用#import來引入標頭檔案,可以防止重複引入標頭檔案,可以避免出現標頭檔案遞迴引入的現象。
  • @class僅用來告訴編譯器,有這樣一個類,編譯程式碼時,不報錯,不會拷貝標頭檔案.如果需要使用該類或者內部方法需要使用 #import匯入

2. id 和 instancetype的區別?

  • id可以作為方法的返回以及引數型別 也可以用來定義變數
  • instancetype 只能作為函式或者方法的返回值
  • instancetype對比id的好處就是: 能精確的限制返回值的具體型別

3. New 作用是什麼?

  1. 向計算機(堆區)申請記憶體空間;
  2. 給例項變數初始化;
  3. 返回所申請空間的首地址;

4.OC例項變數的修飾符? 及作用範圍?

@puplic

 1.可以在其他類中訪問被@public修飾的成員變數
 2.也可以在本類中訪問被@public修飾的成員變數
 3.可以在子類中訪問父類中被@public修飾的成員變數
複製程式碼

@private

1.不可可以在其他類中訪問被@private修飾的成員變數
2.也可以在本類中訪問被@private修飾的成員變數
3.不可以在子類中訪問父類中被@private修飾的成員變數
複製程式碼

@protected (預設情況下所有的例項變數都是protected)

1.不可可以在其他類中訪問被@protected修飾的成員變數
2.也可以在本類中訪問被@protected修飾的成員變數
3.可以在子類中訪問父類中被@protected修飾的成員變數
複製程式碼

@package

介於public和private之間的,如果是在其他包中訪問就是private,在當前程式碼中訪問就是public.
複製程式碼

5. @proprety的作用

@property = ivar + getter + setter;
複製程式碼
  1. 在.h檔案中幫我們自動生成getset方法宣告
  2. 在.m檔案中幫我們生成私有的例項變數(前提是沒有在.h檔案中沒有手動生成)
  3. 在.m檔案中幫我們是實現get和set方法的實現
  • 注意:
    在使用@property情況下,可以重寫getter和setter方法.需要注意的是, 當把setter和getter方法都實現了之後,例項變數也需要手動新增.

6. @proprety 引數說明?

  • 原子性---atomic/nonatomic 如果不寫預設情況為 atomic(系統會自動加上同步鎖,影響效能),在 iOS 開發中儘量指定為 nonatomic,這樣有助於提高程式的效能
  • 讀/寫許可權---readwrite(讀寫)、readooly (只讀)
  • 記憶體管理語義---retain、assign、strong、 weak、unsafe_unretained、copy
  • 方法名---getter=、setter=

7 NSObject和id的區別?

  • NSObject和id都可以指向任何物件
  • NSObject物件會在編譯時進行檢查,需要強制型別轉換
  • id型別不需要編譯時檢查,不需要強制型別轉換

8. id型別, nil , Nil ,NULL和NSNULL的區別?

  • id型別: 是一個獨特的資料型別,可以轉換為任何資料型別,id型別的變數可以存放任何資料型別的物件,在內部處理上,這種型別被定義為指向物件的指標,實際上是一個指向這種物件的例項變數的指標; id 宣告的物件具有執行時特性,既可以指向任意型別的物件
  • nil 是一個例項物件值;如果我們要把一個物件設定為空的時候,就用nil
  • Nil 是一個類物件的值,如果我們要把一個class的物件設定為空的時候,就用Nil
  • NULL 指向基本資料型別的空指標(C語言的變數的指標為空)
  • NSNull 是一個物件,它用在不能使用nil的場合

9. atomic和nonatomic區別,以及作用?

atomicnonatom的主要區別就是系統自動生成的getter/setter方法不一樣

  • atomic系統自動生成的getter/setter方法會進行加鎖操作
  • nonatomic系統自動生成的getter/setter方法不會進行加鎖操作

atomic不是執行緒安全的

  • 系統生成的getter/setter方法會進行加鎖操作,注意:這個鎖僅僅保證了getter和setter存取方法的執行緒安全.
  • 因為getter/setter方法有加鎖的緣故,故在別的執行緒來讀寫這個屬性之前,會先執行完當前操作.
  • atomic 可以保證多執行緒訪問時候,物件是未被其他執行緒銷燬的(比如:如果當一個執行緒正在get或set時,又有另一個執行緒同時在進行release操作,可能會直接crash)

10. 什麼情況使用 weak 關鍵字,相比 assign 有 什麼不同?

  • 在 ARC 中,在有可能出現迴圈引用的時候,往往要通過讓其中一端使用 weak 來解決, 比如:delegate 代理屬性, 自身已經對它進行一次強引用,沒有必要再強引用一次,此時也會使用 weak,自定義 IBOutlet 控制元件屬性一般也使用 weak;當然,也可以使用 strong,但是建議使用 weak

weak 和 assign 的不同點

  • weak 策略在屬性所指的物件遭到摧毀時,系統會將 weak 修飾的屬性物件的指標指 向 nil,在 OCnil 發訊息是不會有什麼問題的; 如果使用 assign 策略在屬性所指 的物件遭到摧毀時,屬性物件指標還指向原來的物件,由於物件已經被銷燬,這時候就產生了野指標,如果這時候在給此物件傳送訊息,很容造成程式奔潰 assigin 可以用於修飾非 OC 物件,而 weak 必須用於 OC 物件

11. 代理使用 weak 還是 assign

  • 建議使用 weak, 對於weak: 指明該物件並不負責保持delegate這個物件,delegate這個物件的銷燬由外部控制。
  • 可以使用 assign,也有weak的功效, 對於使用 assign 修飾delegate, 在物件釋放前,需要將 delegate 指標設定為 nil,不然會產生野指標

12. ARC 下,不顯式指定任何屬性關鍵字時,預設 的關鍵字都有哪些?

  • 基本資料型別: atomic,readwrite,assign
  • 普通的 OC 物件: atomic,readwrite,strong

13. 怎麼用 copy 關鍵字?

  • NSString、NSArray、NSDictionary 等等經常使用 copy 關鍵字,是因為他們有對應 的可變型別:NSMutableString、NSMutableArray、NSMutableDictionary,為確保 物件中的屬性值不會無意間變動,應該在設定新屬性值時拷貝一份,保護其封裝性
  • block 也經常使用 copy 關鍵字,方法內部的 block 預設是 在棧區的,使用 copy 可以把它放到堆區.
  • 對於 block 使用 copy 還是 strong 效果是一樣的,但是 建議寫上 copy,因為這樣顯示告知呼叫者“編譯器會自動對 block 進行了 copy 操 作

14. 如何讓自定義類可以用 copy 修飾符?如何重寫帶 copy 關鍵字的 setter?

若想令自己所寫的物件具有拷貝功能,則需實現 NSCopying 協議。如果自定義的物件分為可變版本與不可變版本,那麼就要同時實現 NSCopyiog 與 NSMutableCopying 協議

// 實現不可變版本拷貝
- (id)copyWithZone:(NSZone *)zone; 
// 實現可變版本拷貝
- (id)mutableCopyWithZone:(NSZone *)zone;
// 重寫帶 copy 關鍵字的 setter
- (void)setName:(NSString *)name {
    _name = [name copy];
}
複製程式碼

15. weak 屬性需要在 dealloc 中置 nil 麼

  • 在 ARC 環境無論是強指標還是弱指標都無需在 dealloc 設定為 nil , ARC 會自動幫我們處理
  • 即便是編譯器不幫我們做這些,weak 也不需要在 dealloc 中置 nil 在屬性所指的物件遭到摧毀時,屬性值也會清空

16.說一下OC的反射機制;

  • OC的反射機制主要是基於OC的動態語言特性;
  • 系統Foundation框架為我們提供了一些方法反射的API;
  • 我們可以通過這些API執行將字串轉為SEL等操作;
  • 由於OC語言的動態性,這些操作都是發生在執行時的。

17.手寫單例

方式一: 不是執行緒安全的,如果多執行緒需要加鎖

static ClassName *_instance;
+ (instancetype)sharedInstance{
   @synchronized (self) {
       if(!_instance)   {
           _instance = [self alloc]init];
       }
    }
    return _instance;
} 
複製程式碼

方式二: 注意多執行緒問題 GCDdispatch_once 預設是執行緒安全的

  static ClassName *_instance;
    + (instancetype)sharedInstance{
        static dispatch_one_t oneToken;
        dispatch_once(&onetoken,^{
           _instance = [self alloc]init];
        });
        return _instance;
    }
    
    + (instancetype)allocWithZone:(NSZone *) zone{
      static dispatch_t onetoken;
      dispatch_once(&oncetoken ^{
         _instance = [super allocwithzone:zone];
      })
      retun _instance
    }
複製程式碼

18. 什麼是殭屍物件?

  • 已經被銷燬的物件(不能再使用的物件),記憶體已經被回收的物件。

19.野指標

  • 指向殭屍物件(不可用記憶體/已經釋放的記憶體地址)的指標

比如:

NSObject *obj = [NSObject new];
[obj release]; // obj 指向的記憶體地址已經釋放了,
obj 如果再去訪問的話就是野指標錯誤了.
野指標錯誤形式在Xcode中通常表現為:Thread 1:EXC_BAD_ACCESS,因為你訪問了一塊已經不屬於你的記憶體。
複製程式碼

20. 什麼是記憶體洩露?

  • 記憶體洩露 :一個物件不再使用,但是這個物件卻沒有被銷燬,空間沒有釋放,則這個就叫做記憶體洩露.
  • ARC導致的迴圈引用 block,delegate,NSTimer等.

21.陣列copy后里面的元素會複製一份新的嗎

  • 不會,陣列裡面存的是之前物件的地址,不會改變,可以自己測試一下

22. 如下程式碼,會有什麼問題嗎?

@property (copy, nonatomic) NSMutableArray * array
複製程式碼

使用 copy 修飾,會生成不可變陣列,在新增刪除陣列元素時候會崩潰

23. OC中的NSInteger 和int 有什麼區別

  • 在32位作業系統時候, NSInteger 等價於 int,即32位
  • 在64位作業系統時候, NSInteger 等價於 long,即64位

24. @synthesize 和 @dynamic 分別有什麼作用

  • @property 有兩個對應的詞,一個是@synthesize,一個是@dynamic
  • 如果 @synthesize 和@dynamic都沒寫,那麼預設的就是@syntheszie var = _var;
  • @synthesize 的語義是如果你沒有手動實現 setter 方法和 getter 方法,那麼編譯器 會自動為你加上這兩個方法
  • @dynamic 告訴編譯器:屬性的 setter 與 getter方法由使用者自己實現,不自動生成(當然對於 readonly 的屬性只需提供 getter 即可)

25.NSMutableDictionary 中使用setValueForKey 和 setObjectForKey有什麼區別?

  • 根據官方文件說明: 一般情況下,如果給NSMutableDictionary 傳送setValue 仍然是呼叫了 setObject方法, 如果引數 value 為 nil,則會呼叫removeObject 移除這個鍵值對;
  • setObjectForKey 是 NSMutableDictionary特有的, value 不能為 nil,否則會崩潰
  • setValueForKey 是KVC的,key 必須是字串型別, setObject 的 key 可以是任意型別

26.列舉出延遲呼叫的幾種方法?

  • performSelector方法
[self performSelector:@selector(Delay) withObject:nil afterDelay:3.0f];
複製程式碼
  • NSTimer定時器
[NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(Delay) userInfo:nil repeats:NO];
複製程式碼
  • sleepForTimeInterval
[NSThread sleepForTimeInterval:3.0f];
複製程式碼
  • GCD方式
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [self Delay];
    });
- (void)Delay {
 NSLog(@"執行"); 
}
複製程式碼

27. NSCache 和NSDictionary 區別?

  1. NSCache可以提供自動刪減快取功能,而且保證執行緒安全,與字典不同,不會拷貝鍵。
  2. NSCache可以設定快取上限,限制物件個數和總快取開銷。定義了刪除快取物件的時機。這個機制只對NSCache起到指導作用,不會一定執行。
  3. NSPurgeableData搭配NSCache使用,可以自動清除資料。
  4. 只有那種“重新計算很費勁”的資料才值得放入快取。

28.NSArray 和 NSSet區別

  • NSSet和NSArray功能性質一樣,用於儲存物件,屬於集合。
  • NSSet屬於 “無序集合”,在記憶體中儲存方式是不連續
  • NSArray是 “有序集合” 它記憶體中儲存位置是連續的。
  • NSSet,NSArray都是類,只能新增物件,如果需要加入基本資料型別(int,float,BOOL,double等),需要將資料封裝成NSNumber型別。
  • 由於NSSet是用hash實現的所以就造就了它查詢速度比較快,但是我們不能把某某物件存在第幾個元素後面之類的有關下標的操作。

29.宣告一個函式,傳入值是一個輸入輸出引數都是 int的 block 函式

- (void)test_Function:(int(^)(int num)) block{}
複製程式碼

30.物件導向和麵向過程的區別?

  • 程式導向:注重的是解決問題的步驟,比如C語言
  • 物件導向:關注的是解決問題的去要那些物件,OC語言就是物件導向

31.物件方法和類方法的區別?

  • 物件方法:以減號開頭,只可以被物件呼叫,可以訪問成員變數
  • 類方法:以加號開頭只能用類名呼叫,物件不可以呼叫,類方法不能訪問成員變數

32. 什麼是程式導向?(POP--Procedure Oriented Programming)

  • “程式導向”(Procedure Oriented)是一種以過程為中心的程式設計思想。就是分析出解決問題所需要的步驟,然後用函式把這些步驟一步一步實現,使用的時候一個一個依次呼叫就可以了。注重的是實現過程!

33. 什麼是物件導向?(OOP--Object Oriented Programming)

  • “物件導向”是一種以物件為中心的程式設計思想。

  • 物件導向的三大特性:

  1. 封裝
    隱藏物件的屬性和實現細節,僅對外提供公共訪問方式,將變化隔離,便於使用,提高複用性和安全性。
  2. 繼承
    提高程式碼複用性;建立了類之間的關係;子類可以擁有父類的所有成員變數的方法;繼承是多型的前提。
  3. 多型
    父類或介面定義的引用變數可以指向子類或具體實現類的例項物件。提高了程式的擴充性。
  • 正因為物件導向程式設計有著著三種特性,繼承、封裝、多型,從而使得物件導向程式設計更具有容易讓人接受,更貼近與人們的生活,比物件導向程式設計更加方便與快捷,一定程度上降低了程式設計師的工作量,使程式的可讀性也得到了提高,程式碼的效率也得到了提高。

34. 什麼是多型?

  • 多型在面嚮物件語言中指同一個介面有多種不同的實現方式,在OC中,多型則是不同物件對同一訊息的不同響應方式;子類通過重寫父類的方法來改變同一方法的實現.體現多型性
  • 通俗來講: 多型就父類型別的指標指向子類的物件,在函式(方法)呼叫的時候可以呼叫到正確版本的函式(方法)。
  • 多型就是某一類事物的多種形態.繼承是多型的前提;

35. 什麼是分類?

  • 分類: 在不修改原有類程式碼的情況下,可以給類新增方法
    Categroy 給類擴充套件方法,或者關聯屬性, Categroy底層結構也是一個結構體:內部儲存這結構體的名字,那個類的分類,以及物件和類方法列表,協議,屬性資訊
  • 通過Runtime載入某個類的所有Category資料
  • 把所有Category的方法、屬性、協議資料,合併到一個大陣列中後面參與編譯的Category資料,會在陣列的前面
  • 將合併後的分類資料(方法、屬性、協議),插入到類原來資料的前面

36.什麼是協議?

  • 協議:協議是一套標準,這個標準中宣告瞭很多方法,但是不關心具體這些方法是怎麼實現的,具體實現是由遵循這個協議的類去完成的。
  • 在OC中,一個類可以實現多個協議,通過協議可以彌補單繼承的缺陷但是協議跟繼承不一樣,協議只是一個方法列表,方法的實現得靠遵循這個協議的類去實現。

37.正式協議&非正式協議?

  • 非正式協議:凡是在NSObject或其子類 Foundation 框架中的類增加類別(分類),都是非正式協議
  • 正式協議: @protocol

38.如何實現多繼承?

  1. 類別
  2. 協議
  3. 訊息轉發 (後面會詳細講述)

39.為什麼說OC是一門動態語言?

  • 動態語言:是指程式在執行時可以改變其結構,新的函式可以被引進,已有的函式可以被刪除等在結構上的變化
  • 動態型別語言: 就是型別的檢查是在執行時做的。

OC的動態特性可從三方面:

  • 動態型別(Dynamic typing):最終判定該類的例項型別是在執行期間
  • 動態繫結(Dynamic binding):在執行時確定呼叫的方法
  • 動態載入(Dynamic loading):在執行期間載入需要的資源或可執行程式碼

40.動態繫結?

  • 動態繫結 將呼叫方法的確定也推遲到執行時。OC可以先跳過編譯,到執行的時候才動態地新增函式呼叫,在執行時才決定要呼叫什麼方法,需要傳什麼引數進去,這就是動態繫結。
  • 在編譯時,方法的 呼叫並不和程式碼繫結在一起,只有在消實傳送出來之後,才確定被呼叫的程式碼。通過動態型別和動態繫結技術,

41. cocoa 和 cocoa touch是什麼?區別?

  • Cocoa包含Foundation和AppKit框架,可用於開發Mac OS X系統的應用程式。
  • Cocoa Touch包含Foundation和UIKit框架,可用於開發iPhone OS系統的應用程式。
  • Cocoa是 Mac OS X 的開發環境,Cocoa Touch是 iPhone OS的開發環境。

42. cocoa touch底層技術架構?

cocoa touch底層技術架構 主要分為4層:

  • 可觸控層 Cocoa Touch : UI元件,觸控事件和事件驅動,系統介面
  • 媒體層 Media: 音視訊播放,動畫,2D和3D圖形
  • Core Server: 核心服務層,底層特性,檔案,網路,位置服務區等
  • Core OS: 記憶體管理,底層網路,硬碟管理

43. 什麼是謂詞?

謂詞(NSPredicate)是OC針對資料集合的一種邏輯帥選條件,類似一個過濾器,簡單實實用程式碼如下:

Person * p1 = [Person personWithName:@"alex" Age:20];
Person * p2 = [Person personWithName:@"alex1" Age:30];
Person * p3 = [Person personWithName:@"alex2" Age:10];
Person * p4 = [Person personWithName:@"alex3" Age:40];
Person * p5 = [Person personWithName:@"alex4" Age:80];
    
NSArray * persons = @[p1, p2, p3, p4, p5];
//定義謂詞物件,謂詞物件中包含了過濾條件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 30"];
//使用謂詞條件過濾陣列中的元素,過濾之後返回查詢的結果
NSArray *array = [persons filteredArrayUsingPredicate:predicate];
複製程式碼

44. 什麼是類工廠方法?

類工廠方法就是用來快速建立物件的類方法, 他可以直接返回一個初始化好的物件,具備以下特徵:

  1. 一定是類方法
  2. 返回值需要是 id/instancetype 型別
  3. 規範的方法名說說明類工廠方法返回的是一個什麼物件,一般以類名首字母小寫開始;

比如系統 UIButton 的buttonWithType 就是一個類工廠方法:

// 類工廠方法
+ (instancetype)buttonWithType:(UIButtonType)buttonType;
// 使用
+ UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
複製程式碼

45. 什麼是糖衣語法?

糖衣語法又叫做語法糖語法鹽,是指在計算機語言中新增某種語法,這種語法對語言的功能沒有影響,但更方便程式設計師使用,增加程式的可讀性,減少程式碼出錯機會

OC中的字面量,其實就是語法糖

NSNumber * number = @1;
NSArray * array = @[@1, @2, @3];
NSDictionary * dict = @{@"key":@"value"};
NSNumber * num1 = array[0];
NSString * value = dict[@"key"];
複製程式碼

46.Svn 和 Git 區別

  • svn 和 git 都是用來對專案進行版本控制以及程式碼管理的.可以監測程式碼及資源的更改變化.有利於實現高效的團隊合作;

  • svn 是集中式的,集中式是指只有一個遠端版本庫,git 是分散式的,分散式有本地和遠端版本庫,本地倉庫都保留了整個專案的完整備份;
    如果儲存遠端版本庫的伺服器掛了,所有人的程式碼都無法提交,甚至丟失版本庫, git則因為有本地版本庫而不會有這個問題。

  • 由於兩者的架構不同,git 和 svn 的分支也是不同的, svn 的分支是一個完整的目錄,包含所有的實際檔案,和中心倉庫是保持同步的,如果某個團隊成員建立新的分支,那麼會同步到所有的版本成員中,所有人都會收到影響. 而 git下建立的分支合併前是不會影響到任何人的.建立分支可以在本地離線進行任何操作.測試無誤後在合併到主分支,然後其他成員才可以看得到.

47.OC中有二維陣列嗎? 如何實現?

OC中沒有二維陣列, 可以通過一維陣列巢狀來實現二維陣列;

// 字面量定義
NSArray * array = @[
                    @[@1,@2,@3,@4,@5],
                    @[@11,@12,@13,@14,@15],
                    @[@21,@22,@23,@24,@25],
                    @[@31,@32,@33,@34,@35],
                    @[@41,@42,@43,@44,@45],
                    ];

// 訪問
NSLog(@"%@",array[1][1]);
複製程式碼

48.CocoaPods理解

CocoaPods 是一個 objc 的依賴管理工具,而其本身是利用 ruby 的依賴管理 gem 進行構建的

  • 想深入瞭解這個命令執行的詳細內容,可以在這個命令後面加上 --verbose。現在執行這個命令 pod install --verbose
  • CocoaPod三方庫,會優先編譯

49. --verbose 和 --no-repo-update有什麼用?

  • verbose意思為 冗長的、囉嗦的,一般在程式中表示詳細資訊。此引數可以顯示命令執行過程中都發生了什麼。
  • pod install或pod update可能會卡在Analyzing dependencies步驟,因為這兩個命令會升級 CocoaPods 的 spec 倉庫,追加該引數可以省略此步驟,命令執行速度會提升。

50. KVC中的集合運算子

  1. 簡單集合運算子:@avg、@sum、@max、@min、@count (只能用在集合物件中,物件屬性必須為數字型別)
  2. 物件操作符:
    @unionOfObjects:返回指定屬性的值的陣列,不去重
    @distinctUnionOfObjects:返回指定屬性去重後的值的陣列
  3. 陣列 / 集體操作符:跟物件操作符很相似,只不過是在NSArray和NSSet所組成的集合中工作的。@unionOfArrays:返回一個陣列,值由各個子陣列的元素組成,不去重 @distinctUnionOfArrays:返回一個陣列,值由各個子陣列的元素組成,去重 @distinctUnionOfSets:和@distinctUnionOfArrays差不多, 只是它期望的是一個包含著NSSet物件的NSSet,並且會返回一個NSSet物件。因為集合不能有重複的值,所以只有distinct操作。

51.簡要說明const,巨集,static,extern區分以及使用?

const

const常量修飾符,經常使用的字串常量,一般是抽成巨集,但是蘋果不推薦我們抽成巨集,推薦我們使用const常量。

- const 作用:限制型別
- 使用const修飾基本變數, 兩種寫法效果一致 , b都是隻讀變數
  const int b = 5; 
  int const b = 5;   
- 使用const修飾指標變數的變數 
  第一種: const int *p = &a 和 int const *q = &a; 效果一致,*p 的值不能改,p 的指向可以改; 
  第二種: int * const p = &a;  表示 p 的指向不能改,*p 的值可以改
  第三種: 
  const int * const p = &a; *p 值和 p 的指向都不能改
  
  const 在*左邊, 指向可變, 值不可變
  const 在*的右邊, 指向不可變, 值可變
  const 在*的兩邊, 都不可變
複製程式碼

巨集

* 基本概念:巨集是一種批量處理的稱謂。一般說來,巨集是一種規則或模式,或稱語法替換 ,用於說明某一特定輸入(通常是字串)如何根據預定義的規則轉換成對應的輸出(通常也是字串)。這種替換在預編譯時進行,稱作巨集展開。編譯器會在編譯前掃描程式碼,如果遇到我們已經定義好的巨集那麼就會進行程式碼替換,巨集只會在記憶體中copy一份,然後全域性替換,巨集一般分為物件巨集和函式巨集。 巨集的弊端:如果程式碼中大量的使用巨集會使預編譯時間變長。

const與巨集的區別?

* 編譯檢查 巨集沒有編譯檢查,const有編譯檢查;
* 巨集的好處 定義函式,方法 const不可以;
* 巨集的壞處 大量使用巨集,會導致預編譯時間過長
複製程式碼

static

* 修飾區域性變數: 被static修飾區域性變數,延長生命週期,跟整個應用程式有關,程式結束才會銷燬,被 static 修飾區域性變數,只會分配一次記憶體
* 修飾全域性變數: 被static修飾全域性變數,作用域會修改,也就是隻能在當前檔案下使用
複製程式碼

extern

宣告外部全域性變數(只能用於宣告,不能用於定義)

常用用法(.h結合extern聯合使用)
如果在.h檔案中宣告瞭extern全域性變數,那麼在同一個類中的.m檔案對全域性變數的賦值必須是:資料型別+變數名(與宣告一致)=XXXX結構。並且在呼叫的時候,必須匯入.h檔案。程式碼如下:

.h
@interface ExternModel : NSObject
extern NSString *lhString;
@end 
.m     
@implementation ExternModel
NSString *lhString=@"hello";
@end

呼叫的時候:例如:在viewController.m中呼叫,則可以引入:ExternModel.h,否則無法識別全域性變數。當然也可以通過不匯入標頭檔案的方式進行呼叫(通過extern呼叫)。
複製程式碼

52.編譯型和解釋型的區別?

  • 編譯型語言: 首先是將原始碼編譯生成機器指令,再由機器執行機器碼 (二進位制)。
  • 解釋型語言: 原始碼不是直接翻譯成機器指令,而是先翻譯成中間程式碼,再由直譯器對中間程式碼進行解釋執行。

53.動態語言和靜態語言?

  • 動態型別語言: 是指資料型別的檢查是在執行時做的。用動態型別語言程式設計時,不用給變數指定資料型別,該語言會在你第一次賦值給變數時,在內部記錄資料型別。
  • 靜態型別語言: 是指資料型別的檢查是在執行前(如編譯階段)做的。

54.什麼是指標常量和常量指標?

  • 常量指標本質是指標,常量修飾它,表示這個指標乃是一個指向常量的指標(變數)。
    指標指向的物件是常量,那麼這個物件不能被更改。

  • 指標常量的本質是一個常量,而用指標修飾它,那麼說明這個常量的值應該是一個指標。
    指標常量的值是指標,這個值因為是常量,所以不能被賦值

55. 指標函式和函式指標

指標函式

  • 指標函式: 顧名思義,它的本質是一個函式,不過它的返回值是一個指標。
// 指標函式
int *sum(int a, int b){
    int result = a + b;
    int *c = &result;
    return c;
}
int *p = sum(10, 20);
printf("sum:%d\n", *p);
複製程式碼

函式指標

  • 與指標函式不同,函式指標 的本質是一個指標,該指標的地址指向了一個函式,所以它是指向函式的指標。
// 函式指標
int max(int a, int b){
    return (a > b)?a:b;
}
int (*p)(int, int) = max;
int result = p(10, 20);
printf("result:%d\n", result);
複製程式碼

56.寫一個標準的巨集MAX,這個巨集輸入2個引數,返回最大一個

#define Max(a,b) a>b?a:b
複製程式碼

57.自定義巨集 #define MIN(A,B) A

float a = 1;
float b = MIN(a++,1.5);
問 a= ? b = ?
答案: a = 3; b = 2
a++ 會後執行, a++在表示式出現了2次,得3,  a++<1.5,返回a++,得2

// 擴充套件
float a = 1;
float b = [self getMix:a++ b:1.5];
- (CGFloat)getMix:(CGFloat ) a b:(CGFloat)b{
   return a>b?a:b;
}
執行 a = 2; b =1;
複製程式碼

下一篇入口:

iOS | 面試知識整理 - OC基礎 (二)

其實呢作為一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是我的微信 大家有興趣可以新增 邀請小夥伴們進入微信群裡一起 交流(想要進入的可加小編微信17512010526)

iOS | 面試知識整理 - OC基礎 (一)

作者:LEON_iOS
連結:www.jianshu.com/p/51c9eb362…


相關文章