0

Similar to this question: XCode 6.3 Warning : Comparison of address of 'myObject' not equal to null pointer is always true

with C++, I found that previously working code for evaluating null pointers stopped working:

struct AStruct
{
    int x, y;
    char *name;
};

AStruct& GetStruct()
{
   return *(AStruct*)0;
}

int main(int argc, const char * argv[]) {

    AStruct& mys = GetStruct();

    if ( ! &mys) {
        printf("null pointer \n");
    }
    else
    {
        printf("NOT a null pointer\n");
    }

    return 0
}

This always prints out NOT a null pointer

I've tried other ways of pointer-to-reference checking:

if ( &mys == NULL)

if ( &mys == nullptr )

None of these worked.

Then I noticed the warning:

Reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false

But there are no suggested fixes.

What is the canonical way of checking null pointers these days?

Community
  • 1
  • 1
kakyo
  • 10,460
  • 14
  • 76
  • 140

2 Answers2

1

You are not checking against a pointer, you are checking against a reference.

References are not supposed to be nullptr since they must refer to an existing value. Indeed what you are doing *(AStruct*)0 is not well defined since a reference shouldn't be able to generate undefined behaviour through "dereferencing it" but in this way you could trigger the problem.

If client code has a AStruct& then it can be sure that the reference points to something, you are breaking this condition.

If you need to work with references that can be null use a pointer, eg

AStruct* GetStruct()
{
  return nullptr;
}

if (!GetStruct())
{
  ...

The fact that the code worked in a previous version of Xcode is a symptom of the fact that this is not well-defined code.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • Thank you. The "Not well-defined code" was rather shocking. I tried to cast `mys` to `int` or `intptr_t` and all that. The value itself is zero too. It even worked when turning off optimization. But with optimization it stops working. Anyways, the original code was not good practice I know. But the values I saw was rather counter-intuitive. – kakyo Jun 18 '15 at 02:40
1

You don't have a pointer there; mys is a reference. Then when you check the value of &mys, you are checking the address of the reference.

Logicrat
  • 4,438
  • 16
  • 22
  • 1
    References don't have addresses, there is no guarantee that they have one since they could have no storage at all. Asking for the address of a reference yields the address of the referenced object. – Jack Jun 18 '15 at 02:03
  • Thank you very much, Jack. I think "Asking for the address of a reference yields the address of the referenced object." is worth adding to your answer below. This is a revelation. It's creepy that printing the address gives me zero though.... – kakyo Jun 18 '15 at 02:42