2

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*

Bikineev
  • 1,685
  • 15
  • 20
  • Do you mean allowed in gcc and error in clang? – Shafik Yaghmour Nov 10 '15 at 18:42
  • Please post complete code. We don't know what `A` and `bar()` are, there could be an overloaded `operator,`, and there could even be macros to furher complicate the issue (as a matter of fact, `NULL` is a macro, so you cannot use it without an `#include`). – Christian Hackl Nov 10 '15 at 18:50
  • I suspect the compiler is converting NULL to the same type as bar's return type since it's part of a comma expression. And then it has trouble converting that to an A pointer. – Anon Mail Nov 10 '15 at 18:51

2 Answers2

3

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;
}
Andrey Nasonov
  • 2,619
  • 12
  • 26
3

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.

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402