Definition of macro NULL in C++
Leon is correct that when there are several overloads for the same function, \0
would prefer the one that takes parameter of type char
. However, it is important to notice that on a typical compiler, NULL
would prefer the overload that takes parameter of type int
, not of type void*
!
What probably causes this confusion is that C language allows defining NULL
as (void*)0
. C++ standard explicitly states (draft N3936, page 444):
Possible definitions [of macro NULL
] include 0
and 0L
, but not (void*)0
.
This restriction is necessary, because e.g. char *p = (void*)0
is valid C but invalid C++, whereas char *p = 0
is valid in both.
In C++11 and later, you should use nullptr
, if you need a null constant that behaves as pointer.
How Leon's suggestion works in practice
This code defines several overloads of a single function. Each overload outputs the type of the parameter:
#include <iostream>
void f(int) {
std::cout << "int" << std::endl;
}
void f(long) {
std::cout << "long" << std::endl;
}
void f(char) {
std::cout << "char" << std::endl;
}
void f(void*) {
std::cout << "void*" << std::endl;
}
int main() {
f(0);
f(NULL);
f('\0');
f(nullptr);
}
On Ideone this outputs
int
int
char
void*
Therefore I would claim that the problem with overloads is not an actual application but a pathological case. The NULL
constant will behave wrong anyway, and should be replaced with nullptr
in C++11.
What if NULL is not zero?
Another pathological case is suggested by Andrew Keeton at another question:
Note that what is a null pointer in the C language. It does not matter on the underlying architecture. If the underlying architecture has a null pointer value defined as address 0xDEADBEEF, then it is up to the compiler to sort this mess out.
As such, even on this funny architecture, the following ways are still valid ways to check for a null pointer:
if (!pointer)
if (pointer == NULL)
if (pointer == 0)
The following are INVALID ways to check for a null pointer:
#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)
as these are seen by a compiler as normal comparisons.
Summary
All in all, I would say that the differences are mostly stylistic. If you have a function that takes int
and overload that takes char
, and they function differently, you will notice difference when you call them with \0
and NULL
constants. But as soon as you place those constants in variables, the difference disappears, because the function that is called is deducted from the type of the variable.
Using correct constants makes the code more maintainable, and conveys meaning better. You should use 0
when you mean a number, \0
when you mean a character, and nullptr
when you mean a pointer. Matthieu M. points out in comments, that GCC had a bug, in which a char*
was compared to \0
, whereas the intention was to dereference the pointer and compare a char
to \0
. Such errors are easier to detect, if proper style is used thorough the codebase.
To answer your question, there is not really an actual use case that would prevent you from using \0
and NULL
interchangeably. Just stylistic reasons and some edge cases.