I included a check for nullptr
in a line of C code. The compiler (gcc) complained when using -std=c17
as well as -std=gnu17
.
Is there such a thing as nullptr (or equivalent) in modern C standards? (C11, C17)
If not, then why?
I included a check for nullptr
in a line of C code. The compiler (gcc) complained when using -std=c17
as well as -std=gnu17
.
Is there such a thing as nullptr (or equivalent) in modern C standards? (C11, C17)
If not, then why?
No, C still uses NULL
for a null pointer.
C++ needs a dedicated null pointer literal because it has overloading and template type deduction. These features get confused by NULL
, which expands to 0
(or something like that) in C++. However, the risk of such confusion in C is small (maybe _Generic
can get confused by this), and in addition, C can use (void*)0
for a null pointer, which mitigates this risk even more.
The closest thing to C++'s nullptr
is C's NULL
. Which may be
- an integer constant expression with the value 0,
- an integer constant expression with the value 0 cast to the type
void*
.A null pointer constant may be converted to any pointer type; such conversion results in the null pointer value of that type.
The formal C17 specifications state that the stddef.h
header defines NULL
"which expands to an implementation-defined null pointer constant." (7.19)
A null pointer constant is defined as follows (6.3.2.3)
- An integer constant expression with the value 0, or such an expression cast to type
void *
, is called a null pointer constant.) 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.- Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
Note that this makes the following program ambiguous, as NULL
could be an integer constant expression (accepted by the function) or of the type void*
(not accepted by the function).
#include <stdio.h>
void printInt(int n)
{
printf("%d\n", n);
}
int main(void)
{
printInt(NULL);
}
Which is why nullptr
was introduced in C++11. For C, having no function overloading or type deduction, this is less of an issue.
ISO C 23 now has nullptr
, as well as the nullptr_t
type. The proposal that introduced it has some rationale.
A null pointer in C is a pointer object pointing at "null". You can turn a pointer into a null pointer by assigning it to a null pointer constant. Valid null pointer constants are 0
and (void*)0
. The macro NULL
is guaranteed to be a null pointer constant.
The internal representation of the pointer then becomes a "null pointer", which could in theory point at an address different from zero on some exotic system. Similarly, NULL
could in theory expand to something different from zero in old, pre-standard C.
When creating C++, Bjarne Stroustrup found all of this to be needlessly complex and decided that "NULL is 0" (source: https://www.stroustrup.com/bs_faq2.html#null). Notably C++ was created long before the first standardization of C, so his arguments are less relevant to standard C than they were to pre-standard C.
For more info about null pointers vs NULL in C, see What's the difference between null pointers and NULL?