Why are NULL pointers defined differently in C and C++?

C++CPointersNull

C++ Problem Overview


In C, NULL is defined as (void *)0 whereas in C++ it is 0. Why is it so? In C I can understand that if NULL is not typecast to (void *) then compilers may/may not generate warning. Other than this, is there any reason?

C++ Solutions


Solution 1 - C++

Back in C++03, a null pointer was defined by the ISO specification (§4.10/1) as

> A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero.

This is why in C++ you can write

int* ptr = 0;

In C, this rule is similar, but is a bit different (§6.3.2.3/3):

> An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

Consequently, both

int* ptr = 0;

and

int* ptr = (void *)0

are legal. However, my guess is that the void* cast is here so that statements like

int x = NULL;

produce a compiler warning on most systems. In C++, this wouldn't be legal because you can't implicitly convert a void* to another pointer type implicitly without a cast. For example, this is illegal:

int* ptr = (void*)0; // Legal C, illegal C++

However, this leads to issues because the code

int x = NULL;

is legal C++. Because of this and the ensuing confusion (and another case, shown later), since C++11, there is a keyword nullptr representing a null pointer:

int* ptr = nullptr;

This doesn't have any of the above problems.

The other advantage of nullptr over 0 is that it plays better with the C++ type system. For example, suppose I have these two functions:

void DoSomething(int x);
void DoSomething(char* x);

If I call

DoSomething(NULL);

It's equivalent to

DoSomething(0);

which calls DoSomething(int) instead of the expected DoSomething(char*). However, with nullptr, I could write

DoSomething(nullptr);

And it will call the DoSomething(char*) function as expected.

Similarly, suppose that I have a vector<Object*> and want to set each element to be a null pointer. Using the std::fill algorithm, I might try writing

std::fill(v.begin(), v.end(), NULL);

However, this doesn't compile, because the template system treats NULL as an int and not a pointer. To fix this, I would have to write

std::fill(v.begin(), v.end(), (Object*)NULL);

This is ugly and somewhat defeats the purpose of the template system. To fix this, I can use nullptr:

std::fill(v.begin(), v.end(), nullptr);

And since nullptr is known to have a type corresponding to a null pointer (specifically, std::nullptr_t), this will compile correctly.

Hope this helps!

Solution 2 - C++

In C, NULL expands to an implementation-defined "null pointer constant". A null pointer constant is either an integer constant expression with the value 0, or such an expression cast to void*. So a C implementation may define NULL either as 0 or as ((void*)0).

In C++, the rules for null pointer constants are different. In particular, ((void*)0) is not a C++ null pointer constant, so a C++ implementation can't define NULL that way.

Solution 3 - C++

The C language was created to make it easier to program microprocessors. A C pointer is used to store the address of data in memory. A way was needed to represent that a pointer had no valid value. The address zero was chosen since all microprocessors used that address for booting up. Since it couldn't be used for anything else zero was a good choice to represent a pointer with no valid value. C++ is backward compatible with C so it's inherited that convention.

The requirement of casting zero when used as a pointer is only a recent add on. Later generations of C wanted to have more rigor (and hopefully fewer errors) so they started being more pedantic about syntax.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionmohit View Question on Stackoverflow
Solution 1 - C++templatetypedefView Answer on Stackoverflow
Solution 2 - C++Keith ThompsonView Answer on Stackoverflow
Solution 3 - C++JayView Answer on Stackoverflow