I know that in our modern world NULL and 0 are not best practices in operating with pointers, and according to cppreference:
Pointer conversions A null pointer constant (see NULL), can be
converted to any pointer type, and the result is the null pointer
value of that type. Such conversion (known as null pointer conversion)
is allowed to convert to a cv-qualified type as a single conversion,
that is, it's not considered a combination of numeric and qualifying
conversions.
But why this code is not allowed and gcc with clang give me an error?
A* foo()
{
return (bar(), NULL);
}
error: invalid conversion from long int to A*
The issue here is that
(bar(), NULL)
is an expression using the comma operator.
In a comma expression E1, E2, the expression E1 is evaluated, its result is discarded, and its side effects are completed before evaluation of the expression E2 begins (note that a user-defined operator, cannot guarantee sequencing).
The type, value, and value category of the result of the comma expression are exactly the type, value, and value category of the second operand, E2. If E2 is a temporary, the result of the expression is that temporary. If E2 is a bit-field, the result is a bit-field.
So the type of (bar(), NULL)
is being determined as a long int
as that is the type of NULL
So it is trying to convert a long int
with the value of NULL
to an A*
which will fail.
If we changed the code to
A* foo()
{
return NULL;
}
This will compile as the value of NULL
is used and the value of NULL
can be assigned to a pointer.
The answer is presented in your question.
A null pointer constant (see NULL), can be converted to any
pointer type, and the result is the null pointer value of that type.
NULL
is constant, bar(), 0
is not constant.
Just compare:
A* foo()
{
return 0;
}
versus
A* foo()
{
int v = 0;
return v;
}
versus
A* foo()
{
const int v = 0;
return v;
}