Objective-C 中 NULL、nil、Nil、NSNull 的定義及不同

在C語(yǔ)言中用0來(lái)作為"不存在"的原始值,而用NULL作為指針空值。在Objective-C中,則有幾種不同的方式來(lái)表示"不存在",分別有:NULL、nil、Nil、NSNull。下面我們來(lái)看看這幾種空值的定義以及使用上的不同。
注: 以下各種空值定義的源碼摘自iOS 10.0 SDK中的相關(guān)頭文件

NULL

NULL定義在user/include/sys/_types/_null.h文件里:

#ifndef NULL 
#define NULL  _ _DARWIN_NULL
#endif  /* NULL */

其中 _ _DARWIN_NULL 的定義在usr/include/sys/_ _types.h文件里,如下:

#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 */

上述代碼首先定義在C++環(huán)境下不同編譯器的_ _DARWIN_NULL的取值,然后定了其他環(huán)境下_ _DARWIN_NULL的值,因此在Objective-C中NULL的最終定義為:

#define NULL ((void*)0)

即NULL本質(zhì)上是:(void*)0。

使用慣例:NULL一般用于表示C指針空值,例如:

int *pointerToInt = NULL;
char *pointerToChar = NULL;
struct TreeNode *rootNode = NULL;

nil

nil定義在usr/include/objc/objc.h文件里:

#ifndef nil
#  if __has_feature(cxx_nullptr)
#    define nil nullptr
#  else
#    define nil __DARWIN_NULL
#  endif
#endif

其中_ _has_feature(cxx_nullptr)用于判斷當(dāng)前環(huán)境是否有C++的nullptr特性,如果有.nil定義為nullptr,否則nil定義為**_ _DARWIN_NULL,所以在Objective-C中nil的最終定義為:

#define nil ((void*)0)

也就是說(shuō),nil本質(zhì)上也是:(void *)0,與NULL一致。

使用慣例:nil用于表示指向Objective-C對(duì)象(id類(lèi)型的對(duì)象,或者使用@interface聲明的OC對(duì)象)的指針為空,例如:

NSString *someString = nil;
NSURL *someURL = nil;
id someObject = nil;
 
if (anotherObject == nil) // do something

Nil

Nil定義在usr/include/objc/objc.h文件里:

#ifndef Nil
#  if __has_feature(cxx_nullptr)
#    define Nil nullptr
#  else
#    define Nil __DARWIN_NULL
#  endif
#endif

與上述nil一致,Nil本質(zhì)上也是:(void *)0。

使用慣例:Nil用于表示指向Objective-C類(lèi)(Class)類(lèi)型的指針為空,例如:

Class someClass = Nil;
Class anotherClass = [NSString class];

NSNull

NSNull定義在NSNull.h文件里:

#import 
 
NS_ASSUME_NONNULL_BEGIN
 
@interface NSNull : NSObject 
 
+ (NSNull *)null;
 
@end
 
NS_ASSUME_NONNULL_END

從上述定義中,我們可知NSNull是一個(gè)Objective-C對(duì)象,是一個(gè)用于表示空值得類(lèi),而且它只有一個(gè)單例方法:+[NSNull null],一般用于在集合對(duì)象中保存一個(gè)空的占位對(duì)象。

使用慣例:在Foundation集合對(duì)象(NSArray、NSDictionary、NSSet等)中,nil通常被用于表示集合對(duì)象結(jié)束的標(biāo)志,因此無(wú)法用nil來(lái)存儲(chǔ)一個(gè)空值,所以一般用[NSNull null]空對(duì)象來(lái)存儲(chǔ)。另外,在NSDictionary的-objectForKey:方法中,如果當(dāng)前字典中key對(duì)應(yīng)的值不存在,該方法會(huì)返回nil,表明當(dāng)前key在字典中未添加,但是如果我們想明確表示某一key已經(jīng)在字典中添加,但是它沒(méi)有值,這時(shí)候就可以用[NSNull null]來(lái)賦值表示。

// 當(dāng) NSArray 里遇到 nil 時(shí),就說(shuō)明這個(gè)數(shù)組對(duì)象的元素截止了,即 NSArray 只關(guān)注 nil 之前的對(duì)象,nil 之后的對(duì)象會(huì)被拋棄。
NSArray *array = [NSArray arrayWithObjects:@"one", @"two", nil];
 
// 錯(cuò)誤的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:nil forKey:@"someKey"];
 
// 正確的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:@"someKey"];

NIL或NSNil

Objective-C中不存在這兩個(gè)符號(hào)!!!

總結(jié)

從上述分析我們可知,不管是NULL、nil還是Nil,它們本質(zhì)上是一樣的,都是(void )0,只是寫(xiě)法不同。這樣做的意義是為了區(qū)分不同的數(shù)據(jù)類(lèi)型,雖然它們值相同,但我們需要理解它們之間的字面意義并用于不同場(chǎng)景,讓代碼更加準(zhǔn)確,增加可讀性。
標(biāo)志 值 含義
NULL (void
)0 C指針的字面空值
nil (id)0 Objective-C 對(duì)象的字面空值
Nil (Class)0 Objective-C 類(lèi)的字面空值
NSNull [NSNull null] 用來(lái)表示空值的Objective-C對(duì)象

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容