NULL
對於學習過 C/C++ 語言的朋友,對 NULL 一定很熟悉吧?這就是在 C/C++ 中的空指針。
在 C 語言中, NULL 是無類型的,只是一個宏,它代表空。我們不研究 C++ 中的 NULL ,因為在 C++11 以後又有了新的定義,我們不深究。
這就是 C 語言中所謂的 NULL ( C++ 的定義比較復雜,這裡不說了):
Objective-C
#if defined(__need_NULL) #undef NULL #ifdef __cplusplus # if !defined(__MINGW32__) && !defined(_MSC_VER) # define NULL __null # else # define NULL 0 # endif #else # define NULL ((void*)0) #endif
這是在 stddef.h
頭文件中聲明的。這是使用了條件編譯的, __cplusplus
這個宏表示 C++ ,對於我們 Objective-C 開發來說, NULL 就表示 ((void*)0)
像 C 語言中,我們定義了一個指針,當我們使用完以後,通常會設置指向 NULL 。如果沒有設置,這個指針就成了所謂的野指針,然後其它地方不小心訪問了這個指針是很容易造成非法訪問的,常見的表現就是崩潰了。
既然 Objective-C 是基於 C 語言的面向對象語言,那麼也會使用到 C 語言類型的指針,比如使用 const char *
類型,判斷是否為空時,是使用 p != NULL
來判斷的。
nil
對於我們學習 Objective-C 的人來說,這個是非常熟悉的。如下為官方定義:
Objective-C
#ifndef nil # if __has_feature(cxx_nullptr) # define nil nullptr # else # define nil __DARWIN_NULL # endif #endif
對於我們 Objective-C 開發來說, nil 就是 __DARWIN_NULL
。看下官方定義:
Objective-C
#ifdef __cplusplus #ifdef __GNUG__ #define __DARWIN_NULL __null #else /* ! __GNUG__ */ #ifdef __LP64__ #define __DARWIN_NULL (0L) #else /* !__LP64__ */ #define __DARWIN_NULL 0 #endif /* __LP64__ */ #endif /* __GNUG__ */ #else /* ! __cplusplus */ #define __DARWIN_NULL ((void *)0) #endif /* __cplusplus */
這個也是條件編譯的,那麼對於我們 Objective-C 開發來說, nil 就代表 ((void *)0)
。
我們使用 nil 表示 Objective-C 對象為空,如 NSString *str = nil
。
Nil
先看看官方是如何聲明的:
Objective-C
#ifndef Nil # if __has_feature(cxx_nullptr) # define Nil nullptr # else # define Nil __DARWIN_NULL # endif #endif
根據條件,我們做 Objective-C 開發的,那麼 Nil 也就是代表 __DARWIN_NULL
,而對於 __DARWIN_NULL
的聲明如下:
Objective-C
#ifdef __cplusplus #ifdef __GNUG__ #define __DARWIN_NULL __null #else /* ! __GNUG__ */ #ifdef __LP64__ #define __DARWIN_NULL (0L) #else /* !__LP64__ */ #define __DARWIN_NULL 0 #endif /* __LP64__ */ #endif /* __GNUG__ */ #else /* ! __cplusplus */ #define __DARWIN_NULL ((void *)0) #endif /* __cplusplus */
這個也是條件編譯的,那麼對於我們 Objective-C 開發來說, Nil 也就代表 ((void *)0)
。
但是它是用於代表空類的。比如:
Objective-C
Class myClass = Nil;
NSNull
先看看官方的聲明:
Objective-C
NS_ASSUME_NONNULL_BEGIN @interfaceNSNull: NSObject <NSCopying, NSSecureCoding> + (NSNull *)null; @end NS_ASSUME_NONNULL_END
由此我們可知, NSNull 是繼承於 NSObject
的類型。它是很特殊的類,它表示是空,什麼也不存儲,但是它卻是對象,只是一個占位對象。
使用場景就不一樣了,比如說服務端接口中讓我們在值為空時,傳空。
Objective-C
NSDictionry *parameters = @{@"arg1" : @"value1", @"arg2" : arg2.isEmpty ? [NSNull null] : arg2};
這只是隨手舉的例子,當然我們也可以不傳這人參數。如果我們要統一,比如通過 runtime
來動態將對象轉成我們的參數時,那麼可以統一將值為 nil 的都設置為 [NSNull null]
區別
NULL 、 nil 、 Nil 這三者對於 Objective-C 中值是一樣的,都是 (void *)0
,那麼為什麼要區分呢?又與 NSNull 之間有什麼區別:
NULL 是宏,是對於 C 語言指針而使用的,表示空指針
nil 是宏,是對於 Objective-C 中的對象而使用的,表示對象為空
Nil 是宏,是對於 Objective-C 中的類而使用的,表示類指向空
NSNull 是類類型,是用於表示空的占位對象,與 JS 或者服務端的 null 類似的含意
總結
以上只是小編的個人見解,如果疑問之處,歡迎留言討論,謝謝大家對腳本之家的支持。