Currently I understand it as a kind of "empty object". But what's it really?
First of all, when you call this:
id someObject = [NSArray array];
someObject
isn't the array object directly but only a pointer to it. That means, if someObject
is equal to 0x1234
there's an object at that address in the memory.
That's the reason why
id someOtherObject = someObject;
doesn't copy the object. Both pointers point now to the same object.
So, how is nil
defined? Let's take a look at the source code:
objc.h
#define nil __DARWIN_NULL /* id of Nil instance */
_types.h
#ifdef __cplusplus
…
#else /* ! __cplusplus */
#define __DARWIN_NULL ((void *)0)
#endif /* __cplusplus */
Looks like nil
is a pointer to the address 0x0.
Let's see what the Objective-C Programming Reference has to say:
Sending Messages to nil
In Objective-C, it is valid to send a message to nil—it simply has no effect at runtime. There are several patterns in Cocoa that take advantage of this fact. The value returned from a message to nil may also be valid: …
The returned values are either nil
, 0 or a struct
with all variables initialized to 0. Which one it is depends on the expected return type. There is an explicit check in the objective-c runtime for messages to nil
, that means it's really fast.
Nil
, nil
, NULL
Those are the 3 types. Here are all the definitions:
#define Nil __DARWIN_NULL /* id of Nil class */
#define nil __DARWIN_NULL /* id of Nil instance */
#define NULL __DARWIN_NULL
#define __DARWIN_NULL ((void *)0)
As can be seen, they are all exactly the same. Nil
and nil
are defined by Objective-C, NULL
comes from C.
What's the difference then? It's only about style. It makes the code more readable.
Nil
is used as a non-existent class: Class someClass = Nil
.nil
is used as a non-existent instance: id someInstance = nil
.NULL
is a pointer to a non-existent memory part: char *theString = NULL
.nil
isn't an empty object but a non-existent one. A method -getSomeObject
doesn't return an empty object if it doesn't exist but returns nil
which tells the user that there is no object.
Maybe this makes sense: (Both would compile and run.)
if (anObject == nil) { // One cannot compare nothing to nothing,
// that wouldn't make sense.
if (anObject) { // Correct, one checks for the existence of anObject
It's not an empty object, it's the lack of any object at all. The rest of the answers cover the other semantics, so I'll leave it at that :)
nil should only be used with pointers, and nil represents a pointer which points to nothing (it's value is zero)
NSString *myString = nil; // myString points to nothing
int x = nil; // invalid, "x" is not a pointer, but it will compile
It's "nothing". But a "nothing" you can send messages to without getting killed as you would if you were trying to call a method on NULL
.
You can look at this question to have more info on NULL
vs. nil
It's a null pointer - a pointer to "nothing".
Formally defined, it is as Joshual defined - a pointer to nothing or a pointer to no object at all.
From a practical, implementation perspective, particularly when dealing with data structures and algorithms, a nill often will represent a sentinel in a data structure or an object that represents "nothing" for example, in a red-black tree, technically, all of the leaf nodes are "nill", but they still have the same or similar properties & operations of a leaf node (color, pointer to a parent, etc.) - in those cases, it is really a "nothing object" ... if that makes any sense.
So, formally, it is a pointer to nothing, in practice, it is often treated as a representation of nothing, but it is never ... null.
One useful way of thinking about nil
is imagining that it's the empty object that "does nothing".
By "does nothing" I mean, any message you send it won't have side effects.
It's "empty" in the sense that when you ask it for the value of any property, it always returns nil
. So it's not holding any values --> it's empty.
(Actually, it's a little more complicated than that, when you ask for the value of a property that returns a type that's NOT an obj-c object. You will get back a pointer-sized 0
. So for any scalar values that are no larger than sizeof(void*)
you get 0
. But if you ask for a struct
or a double
on a 32 bit system, you get an undefined result. I've written about this here.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With