iOS白話串2-void、void * 、id、NSObject 和 nil、Nil、NSNull、NULL

1 void、void * 、id

1.1 void 和 void *

1.1.1 void

  • 關鍵字表示“空類型”的抽象概念
  • 但這里的“空類型”不表示“任意類型”,實際上它也不是一種類型,而是表示不存在的意思,也就是說C/C++不允許你寫語句void a,不存在類型為void的東西
  • 作用:
    1、對函數返回值進行限定
    - (void)viewDidLoad {
    }
    
    2、對函數傳入參數進行限定
    // 沒有參數的 block 屬性
    @property (nonatomic, copy) void(^clickBlock)(void);
    

1.1.2 void *

  • void *表示“任意類型的指針” 或 表示“該指針與一地址值相關,但是不清楚在此地址上的對象的類型”。

為什么不用void表示任意類型的數據呢?
大家都知道,C/C++是靜態類型的語言,定義變量就會分配內存,然而,不同類型的變量所占內存不同,如果定義一個任意類型的變量,如何為其分配內存呢?所以,C、C++中沒有任意類型的變量。
但是,所有指針類型的變量,無論是int、char、string、Student等等,他們的內存空間都是相同的,所以可以定義“任意類型的指針”。

  • void * 指針只支持幾種有限的操作:
    1 與另一個指針進行比較
    2 向函數傳遞void * 指針或從函數返回void * 指針
    3 給另一個void *指針賦值

不允許使用void * 指針操作它所指向的對象,例如,不允許對void * 指針進行解引用
不允許對void * 指針進行算術操作

1.1.2 REF

C語言void關鍵字_C語言中文網
C/C++中的函數中的void和void* 理解 - 程序園

1.2 id、NSObject

1.2.1 id 定義 和 官方解析-id

id define
  • id是一個指針,用于表示OC 任意類型實例對象的指針,默認告訴編譯器該指針指向的對象可以調用任何方法,下面情況編譯通過
id aObject = nil;
[aObject appendString:@"xx"];

1.2.2 NSObject

1.2.3 id 和 NSObject 定義對比

NSObject定義:typedef struct objc_object NSObject;
id 定義typedef struct objc_object *id;
其中 objc_object 定義:

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};
  • 所以,NSObject 是 objc_object類型結構體的別名,而 id 則是 objc_object類型結構體的的指針
  • id obj = [[NSObject alloc] init]; 等同于 NSObject *obj = [[NSObject alloc] init];

1.2.4 id 等同于 NSObject *嗎

  • 不等同,id 沒有指定類型,而NSObject *則指定了類型即NSObject
    id 編譯通過
    id aObject = nil;
    [aObject appendString:@"xx"];
    
    NSObject *編譯不通過
    NSObject *aObject = nil;
    [aObject appendString:@"xx"]; // error: No visible @interface for 'NSObject' declares the selector 'appendString:'
    
  • 還需要理解一點就是,NSObject 是 OC 的基類,但是 OC 并非所有類都繼承自 NSObject,例如 NSProxy 類。或自定義的其他 OC 類,那么此時就需要引入 id來表示。
  • 同上道理,id 一般用于 delegate 的聲明,因為一般情況下是不知道 delegate 的實際類型是什么

REF

1.3 id 和 void *

  • id is a pointer to any type, but unlike void * it always points to an Objective-C object
  • id 的定義typedef struct objc_object *id;,也就表明,它是表示一個結構體類型,而不是空 void 類型。在內存分布上即存放該指針的內存

2 nil、Nil、NSNull、NULL

  • nil:指向一個對象的空指針(用于表示OC中的實例對象)
NSString *str = nil;
  • Nil:指向一個類的空指針(用于表示OC中的類對象)
Class someClass = Nil;
  • NSNull:用于表示集合對象(NSArray,NSDictionary,NSSet)中的空值
    在集合對象中nil代表結束,故不能用nil代表空值存放于集合中
NSArray *arr = @[@"1", @"2", @"3", [NSNull null]];
  • NULL:指向其他類型(基本數據類型,C語言類型)的空指針
// void * 類型的 context 參數,一般使用調用時,如果想不傳參給 context,此時正確做法是傳入 NULL
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;

[self.person1 addObserver:self forKeyPath:@"age" options: NSKeyValueObservingOptionNew context:NULL]
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容