Page 1 of 1

nullptr is never 0!

Posted: March 12th, 2018, 4:02 am
by cyboryxmen
I had more than enough encounters with junior programmers about this that I decided to make a thread about it. For those of you who are unfamiliar with nullptr, nullptr is a pointer value that you set pointers with to indicate that they are not pointing to anything. That way, you can write code like this:

Code: Select all

// If p is not pointing to anything.
if ( p == nullptr )
	// We don't need to process p since it points to nothing.
This makes nullptr incredibly useful for providing 'optional parameters' for functions where you can just pass nullptr instead of being forced to create an unnecessary object. It is also good for representing objects that can be 'destroyed' during the runtime of the program. Nullptr would then be used to indicate that the object simply doesn't exist anymore. Lastly, it can also be used for search algorithms too. If a search function is made to return an object that matches the search but it can't find anything, nullptr can be returned to indicate this.

Code: Select all

auto obj = Object.search_by_name ( "placeholder" );

// If we found obj.
if ( obj != nullptr )
	// Process obj.
On most systems, the value of nullptr is going to be 0. This is where junior programmers usually misunderstand. Nullptr is never ever 0! It is technically 0 on most systems but it is still not 0!

Simply put, the value of nullptr is null. As in no value! The value is nonexistence itself! It's the difference between being at position [0, 0] and having no position at all! What's the position of 'orgin'? [0, 0]. What's the position of the colour red? Null. As in no value. Because it simply does not make any sense for colours to have a position!

Usually though, this distinction doesn't become apparent and won't cause any problems. Like I said, nullptr is 0 for most systems. This is because pointer value 0 is unusable on most systems so they use it to represent null. However, that's not always the case. It could very well be the complete opposite. Instead of 0, it is actually the biggest value pointer types can represent. Standard loops would normally look like this:

Code: Select all

for ( auto index = 0; index < max; ++index )
	// Do something with i
The loop starts index at 0 and stops processing it when it reaches max. Index will never be processed as max and thus, max will always be an unused value. 0 on the other hand is the first value index will be processed as. Logically speaking, it makes more sense for the maximum value to represent null rather than 0.

This distinction is also crucial at understanding other types that have null values. std::string::find() searches for a substring inside another string and returns the substring's position in that string. If it can't find the substring in the string, it returns a null value called std::string::npos. If you have this concept where null == 0, you would think that if find() returns a 0 value, it means that it didn't find anything and is returning null. That's not the case at all. find() returning 0 would just mean that the substring it found is at the 0th location. So what is the value of npos if it is not 0? Simple: it is null; nonexistence. That's all you ever need to know to use it.

Future hardware may even give us the ability to directly represent the concept of 'null' so we don't have to use an actual value to represent it. By enforcing the concept that null == null and not null == 0 or even null = maximum value, we can prepare ourselves for this possible future saving us the trouble of refactoring our code later down the line. Regardless, I hope this convinces you to start learning this concept before it leads to bugs or confusion in the code.

P.S. All pointer types in C++, when zero initialised, will be set to nullptr even if nullptr is not actually 0.

Code: Select all

int* p { }; // Zero initialised pointer. A misnomer since it won't always initialise the pointer to 0 but rather nullptr!
P.S.S There's also this video that helps reinforce the concept of null.