前言
記得曾經(jīng)有不少朋友問過筆者,在Objective-C
中nil
和Nil
以及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
語言中所謂的NULL
(C++
的定義比較復(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ū)別
NULL
、nil
、Nil
這三者對(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ù)!!!