nil、Nil、NULL和NSNull區(qū)別

前言

記得曾經(jīng)有不少朋友問過筆者,在Objective-CnilNil以及NULL的區(qū)別。最重要的是,在面試中還有不少朋友常會(huì)被問到。記得當(dāng)年剛找工作的時(shí)候,筆者就被面試官問到過,現(xiàn)在筆者在這里統(tǒng)一詳細(xì)說明。

NULL

對(duì)于學(xué)習(xí)過C/C++語言的朋友,對(duì)NULL一定很熟悉吧?這就是在C/C++中的空指針。

C語言中,NULL是無類型的,只是一個(gè)宏,它代表空。我們不研究C++中的NULL,因?yàn)樵?code>C++11以后又有了新的定義,我們不深究。

這就是C語言中所謂的NULLC++的定義比較復(fù)雜,這里不說了):

#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這個(gè)宏表示C++,對(duì)于我們Objective-C開發(fā)來說,NULL就表示((void*)0)

C語言中,我們定義了一個(gè)指針,當(dāng)我們使用完以后,通常會(huì)設(shè)置指向NULL。如果沒有設(shè)置,這個(gè)指針就成了所謂的野指針,然后其它地方不小心訪問了這個(gè)指針是很容易造成非法訪問的,常見的表現(xiàn)就是崩潰了。

既然Objective-C是基于C語言的面向?qū)ο笳Z言,那么也會(huì)使用到C語言類型的指針,比如使用const char *類型,判斷是否為空時(shí),是使用p != NULL來判斷的。

nil

對(duì)于我們學(xué)習(xí)Objective-C的人來說,這個(gè)是非常熟悉的。如下為官方定義:

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

對(duì)于我們Objective-C開發(fā)來說,nil就是__DARWIN_NULL。看下官方定義:

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

這個(gè)也是條件編譯的,那么對(duì)于我們Objective-C開發(fā)來說,nil就代表((void *)0)

我們使用nil表示Objective-C對(duì)象為空,如NSString *str = nil

Nil

先看看官方是如何聲明的:

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

根據(jù)條件,我們做Objective-C開發(fā)的,那么Nil也就是代表__DARWIN_NULL,而對(duì)于__DARWIN_NULL的聲明如下:

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

這個(gè)也是條件編譯的,那么對(duì)于我們Objective-C開發(fā)來說,Nil也就代表((void *)0)

但是它是用于代表空類的。比如:

Class myClass = Nil;

NSNull

先看看官方的聲明:

NS_ASSUME_NONNULL_BEGIN

@interface NSNull : NSObject <NSCopying, NSSecureCoding>

+ (NSNull *)null;

@end

NS_ASSUME_NONNULL_END

由此我們可知,NSNull是繼承于NSObject的類型。它是很特殊的類,它表示是空,什么也不存儲(chǔ),但是它卻是對(duì)象,只是一個(gè)占位對(duì)象。

使用場(chǎng)景就不一樣了,比如說服務(wù)端接口中讓我們?cè)谥禐榭諘r(shí),傳空。

NSDictionry *parameters = @{@"arg1" : @"value1",
                            @"arg2" : arg2.isEmpty ? [NSNull null] : arg2};

這只是隨手舉的例子,當(dāng)然我們也可以不傳這人參數(shù)。如果我們要統(tǒng)一,比如通過runtime來動(dòng)態(tài)將對(duì)象轉(zhuǎn)成我們的參數(shù)時(shí),那么可以統(tǒng)一將值為nil的都設(shè)置為[NSNull null]

區(qū)別

NULLnilNil這三者對(duì)于Objective-C中值是一樣的,都是(void *)0,那么為什么要區(qū)分呢?又與NSNull之間有什么區(qū)別:

  • NULL是宏,是對(duì)于C語言指針而使用的,表示空指針
  • nil是宏,是對(duì)于Objective-C中的對(duì)象而使用的,表示對(duì)象為空
  • Nil是宏,是對(duì)于Objective-C中的類而使用的,表示類指向空
  • NSNull是類類型,是用于表示空的占位對(duì)象,與JS或者服務(wù)端的null類似的含意

寫在最后

以上只是筆者個(gè)人見解,不代表百分百正確,如果疑問之處,請(qǐng)?jiān)谠u(píng)論處留言,筆者會(huì)回復(fù)!!!

以上只是筆者個(gè)人見解,不代表百分百正確,如果疑問之處,請(qǐng)?jiān)谠u(píng)論處留言,筆者會(huì)回復(fù)!!!

以上只是筆者個(gè)人見解,不代表百分百正確,如果疑問之處,請(qǐng)?jiān)谠u(píng)論處留言,筆者會(huì)回復(fù)!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容