Is every null pointer constant a null pointer?
From the C17 draft (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.67) 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.67)The macro
NULL
is defined in<stddef.h>
(and other headers) as a null pointer constant [...].
From this, it follows that the following are null pointer constants: 0
, 0UL
, (void *)0
, (void *)0UL
, NULL
.
It further follows that the following are null pointers: (int *)0
, (int *)0UL
, (int *)(void *)0
, (int *)(void *)0UL
, (int *)NULL
. Interestingly, none of these are "null pointer constants"; see here.
The following null pointer constants are null pointers (because void *
is a pointer type and 0
and 0UL
are null pointer constants): (void *)0
, (void *)0UL
. In this regard, according to the C17 draft (6.2.5 ¶19-20):
The
void
type comprises an empty set of values; it is an incomplete object type that cannot be completed.
[...]
A pointer type may be derived from a function type or an object type, called the referenced type. [...] A pointer type is a complete object type.
void
is not a pointer type itself, and it is an incomplete object type. But void *
is a pointer type.
But it seems that the following are null pointer constants which are not null pointers (because there is no cast to a pointer type): 0
, 0UL
, NULL
. (To be precise, while the standard only requires that NULL
be defined as "a null pointer constant", it would be permissible to define it as a null pointer constant which is also a null pointer. But it seems that the standard doesn't require NULL
to be defined in such a way that it is simultaneously a null pointer.)
Is every null pointer constant a null pointer? (Is NULL
really not a null pointer?)
Finally (and somewhat tongue-in-cheek): In case certain null pointer constants are not null pointers, would they technically be a kind of "non-null pointer"? (This wording appears in some places in the standard.) Note that linguistically we have a so-called bracketing paradox; we can read this as "[non-null] pointer" or "non-[null pointer]".
--------------------------------------------------------------------------------------------------------------
No. In fact, no null pointer constant is a null pointer! This is because constants and pointers are different kinds of entities.
A null pointer constant is a constant expression which has a particular form. An expression is a sequence of tokens, and null pointer constants are defined as sequences of tokens that have a particular form.
A null pointer is a value. In C, each type has its set of potential values. For each pointer type, one or more value in that set is a null pointer. The C standard does not define the concept of value formally. A formal semantics would need to do this (and formally defining values of pointers gets rather complicated, which is why the C standard, an English document written without mathematics, doesn't try).
An expression evaluates to a value in a context (possibly causing side effects). All null pointer constants whose type is a pointer type evaluate to a null pointer. Some null pointer constants (e.g. 0
, 1L - 'z' / 'z'
) have an integer type, and those do not evaluate to a null pointer: they evaluate to a null integer (i.e. an integer with the value 0 — the C standard does not use the expression “null integer” because it isn't anything remarkable that would need a specific name).
The C standard guarantees that if e is a constant expression with an integer type and the value 0, then any expression that converts this value to a pointer type evaluates to a null pointer. Note that this guarantee is not given for arbitrary expressions: (void*) f()
might not be a null pointer even if f
is defined as int f(void) { return 0; }
.
The C standard allows NULL
to have either an integer type or a pointer type. If it has a pointer type, the expression NULL
evaluates to a null pointer. If it has an integer type, it doesn't.
---------------------------------------------------------------------------------------------------------------
Is every null pointer constant a null pointer?
TL;DR: no.
As you have already observed, integer constant expressions with value 0 are null pointer constants, despite not having pointer type. You have also quoted the specification's definition of null pointer: "a null pointer constant [] converted to pointer type". That means that null pointer constants of this general form ...
(void *)(<integer constant expression with value 0>)
... satisfy the definition of "null pointer". The integer constant expression is a null pointer constant itself, so the cast makes the overall expression a null pointer (in addition to being a null pointer constant).
On the other hand, null pointer constants that take the form of integer constant expressions with value 0 do not satisfy the definition of "null pointer", and there is no other provision in the language spec that would make them null pointers. Examples: 0
, 0x00UL
, 1 + 2 + 3 - 6
.
it seems that the standard doesn't require NULL to be defined in such a way that it is simultaneously a null pointer.
Correct.
Is every null pointer constant a null pointer?
Definitely not (see above), but for most purposes, it does not matter.
(Is
NULL
really not a null pointer?)
It depends on your C implementation. The language spec allows either answer. In practice, it is a null pointer in most implementations you're likely to meet.
In case certain null pointer constants are not null pointers, would they technically be a kind of "non-null pointer"?
No. Null pointer constants that are not null pointers are not pointers at all. They are integers.
0 Comments
If you have any doubts, Please let me know