A null value is also a special value. In everyday programming, the obvious is indispensable, but are you using it correctly?

Without further ado, conclusion:

  • Nil: Usually used to represent a null pointer to an instance object, such as id obj = nil;
  • Nil: Usually used to represent a null pointer to a Class object, such as Class CLS = Nil;
  • NULL: Usually used to indicate a NULL pointer to a non-object type (basic data type, C type), such as char * C = NULL;
  • NSNull: Usually used in collection objects to represent null values, such as NSArray * arr = @[[NSNull null]];

So where did the above conclusion come from? Authoritative we still want to start from the official, such as the official source code. Direct download

nil

The definition of nil can be found directly in the source code:

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

The use of nil for global search source code is primarily for null Pointers to instance objects, as mentioned above.

Nil

Also, we can find the definition in the source code:

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

See? Nil is exactly the same as nil! Why is that?

Nil is mainly used for null Pointers to class objects, which seems to be the official source code as a convention. Why not keep up with it?

NULL

Speaking of NULL, the definition is slightly different from the source code (stddef.h) :

#undef NULL
#ifdef __cplusplus
#if __cplusplus >= 201103L
#define NULL nullptr
#else
#undef __null  // VC++ hack.
#define NULL __null
#endif
#else
#define NULL ((void*)0)
#endif
Copy the code

#define NULL ((void*)0) #define NULL (void*)0) Is it the familiar form of a pointer to a primitive data type?

In conjunction with its source code, NULL is used for NULL Pointers of non-object types.

A short summary

In fact, we notice that __DARWIN_NULL in the nil, nil definition is actually NULL:

#ifndef __DARWIN_NULL
#define __DARWIN_NULL NULL
#endif
Copy the code

The __has_feature(cxx_nullptr) is used to determine whether C++11 nullptr is supported or not.

Nullptr is a pointer null type in C++.

Is that all clear at this point?

So far, we’ve actually seen that nil, nil, and NULL have the same values in certain scenarios, which means they can be used interchangeably in those scenarios, especially nil and nil, but in our normal development, it’s probably best not to do that, because on the one hand it’s an official convention, There may also be problems caused by inconsistencies.

There’s a simple, clear rule, and there’s no risk of getting it wrong. Why not?

NSNull

And finally, we’re left with NSNull, so why break it out? Because it’s not the same thing at all.

NSNull is a subclass of NSObject:

@interface NSNull : NSObject <NSCopying.NSSecureCoding>
+ (NSNull *)null;
@end
Copy the code

The header file shows that he has a class method, which is actually a method to get its singleton.

The usage scenarios are mainly in some collection objects, as follows:

// used in an array
NSArray *array = [NSArray arrayWithObjects:
                      [[NSObject alloc] init],
                      [NSNull null],
                      @"aaa".nilThe [[NSObject alloc] init],
                      [[NSObject alloc] init], nil];
NSLog(@"%ld", array.count); // Output 3, NSArray ends in nil

// use in the dictionary
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
                                @"Object0".@"Key0".@"Object1".@"Key1".nil.@"Key-nil"
                                @"Object2".@"Key2".nil];
NSLog(@ "% @", dictionary); // Prints 2 key-values,NSDictionary also ends in nil

// to be used in mutable dictionaries
NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc] init];
[mutableDictionary setObject:nil forKey:@"Key-nil"]; // Can cause a Crash
[mutableDictionary setObject:[NSNull null] forKey:@"Key-nil"]; // Does not cause a Crash
// Therefore, the following methods are relatively safe to use
[mutableDictionary setObject:(nil == value ? [NSNull null] : value)
                      forKey:@"Key"];
Copy the code

Oh, that’s it. Do you understand the use of various null values? I hope they all work out.