1

I am new to C++. I expected two pointers that don't point to anything to be detected as null pointers. However this works only with one of them. The physical addresses of those pointers are somewhat different - 0xe00000001 vs 0x0 (this one is properly detected as null pointer).

I've written the following snippet of code:

#include <iostream>
using namespace std;

struct TNode {
    TNode* Parent;  // Pointer to the parent node
    TNode* Left;  // Pointer to the left child node
    TNode* Right;  // Pointer to the right child node
    int Key;  // Some data
};

int main() {
    TNode parent;
    parent.Key = 2;
    TNode first;
    first.Key = 1;
    first.Parent = &parent;
    parent.Left = &first;
    cout << first.Left << endl; // get 0xe00000001 here
    cout << first.Right <<endl; // get 0x0

    if (first.Right == nullptr) {
        cout <<"rnull"<<endl; // rnull
    }
    if (first.Left == nullptr) {
        cout <<"lnull"<<endl; // nothing
    }

   return 0;
}

What is going on here? Basically, I want to find a way to check whether first.Left points to nothing.

Anastasia
  • 184
  • 11
  • 2
    You have to initialize your struct members explicitely, there's nothing doing that by default. – πάντα ῥεῖ May 03 '19 at 23:40
  • 1
    It is only in rare, well documented cases that you should expect C++ to do something which you do not explicitly ask for. If you want a variable initialized, most of the time you have to initialize it. In this case you can take advantage of [Zero Initialization](https://en.cppreference.com/w/cpp/language/zero_initialization) falling through to [Aggregate Initialization](https://en.cppreference.com/w/cpp/language/aggregate_initialization) to make the compiler zero `first` for you by adding a set of curly braces: `TNode first{};` Personally I'd add a constructor so forgetting is impossible. – user4581301 May 03 '19 at 23:46
  • One common case for automatic zeroing is static variables ([Storage class specifiers](https://en.cppreference.com/w/cpp/language/storage_duration)) – user4581301 May 03 '19 at 23:52
  • Uninitialised pointers are not equal to `nullptr` by default. In fact, comparing them with `nullptr` gives undefined behaviour. If you intend for them to be equal to `nullptr` then initialise them accordingly BEFORE comparing them. – Peter May 04 '19 at 01:46

2 Answers2

5

In your example, first.Left and first.Right are uninitialized, not null. This means that they basically contain whatever garbage was on the stack at the time they were allocated. Accessing the actual value (by printing the pointer, for example) is actually undefined behavior, but with most compilers on low optimization settings it'll just print that garbage.

Solution 1: give default values to member variables

If you want them to be null, you can modify TNode so that their initial value is guaranteed to be null:

struct TNode {
    TNode* Parent = nullptr;
    TNode* Left = nullptr;
    TNode* Right = nullptr; 
    int Key = 0;
};

int main() {
    TNode n; //Everything initialized to null or 0
}

This will guarantee that they're null.

Solution 2: Define TNode() to initialize members

Alternatively, you could also explicitly define the constructor so that it makes everything null

struct TNode {
    TNode* Parent, Left, Right;
    // Everything gets default-initialized to null
    TNode() : Parent(), Left(), Right() {}
};

int main() {
    Tnode n; // Everything initialized to nullptr or 0
}

Solution 3: default-initialize at the point of use

Even if you don't explicitly define a constructor, everything gets initialized to 0 (or null, if it's a pointer) when you explicitly initialize it by putting {} when declaring the variable.

struct TNode {
    TNode* Parent, Left, Right;
    int Key;
};

int main() {

    TNode iAmUninitialized; // This one is uninitialized

    Tnode iAmInitialized{}; //This one has all it's members initialized to 0
}
Alecto Irene Perez
  • 10,321
  • 23
  • 46
0

First of all, in C and C++ there is no such thing as a pointer that points to nothing. Regardless of the value in the pointer, it points at something. Even NULL is a pointer to address "0" but we use that, by convention to represent a NULL. The problem with a pointer that is uninitialized is that it can point to anything and that anything is likely an illegal address which will cause an exception or it points to something else in the application and, if the data is modified, will cause an undesired side-effect.

In your case the 2nd pointer is 0x00 and that is NULL. The 1st pointer, however, is 0x01, and that is NOT NULL.

jwh20
  • 646
  • 1
  • 5
  • 15
  • 1
    `there is no such thing as a pointer that points to nothing. Even NULL is a pointer to address "0"` - no ([1](https://softwareengineering.stackexchange.com/a/128447/30872), [2](https://stackoverflow.com/a/2759875/11683)). `but we use that, by convention to represent a NULL` - it's [the other way round](https://stackoverflow.com/a/177007/11683). – GSerg May 04 '19 at 00:02
  • `NULL` is not required to be a pointer. It’s a macro that expands to a null pointer constant. It is typically defined as `#define NULL 0`, i.e., it’s an `int` value. When you assign that value to a pointer you get a null pointer. But even then, the value of that pointer is not required to be 0. It often is, but reasoning about that value is meaningless l – Pete Becker May 04 '19 at 00:05
  • 1
    A null pointer, by convention, is a value that indicates the pointer doesn't point at anything. An uninitialised pointer is not the same thing. – Peter May 04 '19 at 01:47