Currently I understand it as a kind of "empty object". But what's it really?
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
Maybe I'm just missing the obvious but this seems like a semantic question. As in, you can use lots of different words to describe it, but your description works well enough already.
http://en.wikipedia.org/wiki/Null%5F%28computer%5Fprogramming)
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 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 :)
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.)
Just to clarify, in Objective-C nil and null are not the same thing. Neither do they represent the same thing in Objective-C as they do in mathematics or other programming languages.
Nil is actually a special memory address of 0x0 (at least the compiler treats it as an address.) Nil is used as the address of an object that is named but not allocated. This allows for test for the existence/allocation of named objects as well as providing a safe way to send messages to objects that might not exist. While in math and some languages you can compare scalar variables to nil, in Objective-c, you should not. You should only compare the address of objects.
NULL by contrast can mean either the standard C defined as an integer value ofNULL==0
or it can represents an actual allocated object of the class NSNull with a specific address in memory. NSNull is however, a singleton object i.e. only one exist for every application. It is used as placeholder for other objects usually in collections. You cannot use it in comparisons with any other object. You can only check if a particular pointer points to the singleton NSNull object. Note however that as an allocated object[NSNull null]!=NULL
,
The confusion between nil and NULL arises because assigning an address of NULL assigns it to the nil address of 0x0. Such code works but can cause subtle problem at times. It's best to get in the habit of not confusing the two.
So, in Objective-C, nil, NUll and NSNull are three different but overlapping concepts that are easy to confuse. Nil should be used for addresses, NULL should be used for scalar values and NSNull should be used as a placeholder for allocated objects.
Objective-C objects
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.
Pointer to 0x0
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.
So what?
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-existant class:Class someClass = Nil
.nil
is used as a non-existant instance:id someInstance = nil
.NULL
is a pointer to a non-existant memory part:char *theString = NULL
.
Short
nil
isn't an empty object but a non-existant 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