If I write
int zero = 0;
void *p1 = (void *)0;
void *p2 = (void *)(int)0;
void *p3 = (void *)(0 /*no-op, but does it affect the next zero?*/, 0);
void *p4 = (void *)zero; // For reference, this is a pointer to address zero
void *p5 = 0; // For reference, this is a null pointer
void *p6 = NULL; // For reference, this is a null pointer
void *p7 = nullptr; // For reference, this is a null pointer (C++11)
static const int static_zero_1 = 0; // Is this a literal zero when used?
static const int static_zero_2 = 1 - 1; // No "literals 0" per se... is it?
void *p8 = (void *)static_zero_1; // I have seen weird substitution rules...
void *p9 = (void *)static_zero_2; // do they apply for NULL too?
which of p1
, p2
, and p3
(edit: I added p8
and p9
) would be null pointers (i.e. == NULL
, may or may not be address zero), and which of them would be pointers with the address zero (may or may not be == NULL
)?
If the answer is different in C and C++, what is it in each of them?
p1
and p2
are null pointers; p3
is implementation defined,
and may be something else. (A comma operator cannot be part of
a constant expression. And the mapping of a non-constant
integral value 0 to a pointer is implementation defined.) C is
identical to C++ here.
p8
and p9
are both null pointers in C++, but not in C.
With regards to your comment on static_zero_2
, there is no
requirement in either language that a literal zero be present,
anywhere. g++ defines NULL
as the compiler built-in __null
,
for example, and you can use (1 - 1)
, or '\0'
, or any other
constant expression evaluating to 0.
And to make Andy's answer complete with C:
From the C99 Standard:
6.3.2.3 Pointers
1 A pointer to void may be converted to or from a pointer to any incomplete or object
type. A pointer to any incomplete or object type may be converted to a pointer to void
and back again; the result shall compare equal to the original pointer.
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.
So any integer constant expression which evaluates to 0
is a null pointer constant and can be converted to a NULL
pointer. Effectively in your example, all pointers through except p4
, p8
and p9
are null pointers. p4
, p8
and p9
need not be null pointers since their initialization is not a constant expression because it contains variables (even if const
qualified).
Here's another answer about NULL
in C++, for the record.
which of p1
, p2
, and p3
would be null pointers?
In C++11, all of them. Per paragraph 4.10/1 of the C++11 Standard:
A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to
zero or a prvalue of type std::nullptr_t
. [...]
Therefore, according to the terminology of the Standard, everything which is a constant (integral) expression and evaluates to 0
is a null pointer constant (not a null pointer, yet). The only one which is not a constant expression that evaluates to 0
or a prvalue of type nullptr_t
in your example is zero
, because it is not a constant expression.
The paragraph continues:
A null pointer constant can be converted to a pointer type; the
result is the null pointer value of that type and is distinguishable from every other value of object pointer or
function pointer type. Such a conversion is called a null pointer conversion. Two null pointer values of the
same type shall compare equal.
So in your example all the pointers except p4
are null pointer values and compare equal among themselves.