1

The node Class is as follow:

class node
{
    public:

    int data; //the datum
    node *next; //a pointer pointing to node data type
};

The PrintList Function is as follow:

void PrintList(node *n)
{   while (n != NULL)
    {
        cout << n->data << endl;
        n = n->next;
    }
}

If I try running it I get all three values (1,2,3) but I get an additional number as well which I'm unable to figure out what it represents, Can someone throw light on the same?

int main()
{

    node first, second, third;
    node *head = &first;
    node *tail = &third;
    first.data = 1;
    first.next = &second;
    second.data = 2;
    second.next = &third;
    third.data = 3;

    PrintList(head);    
}

I Know it can be fixed with

third.next = NULL;

But I am just curious what does this number represents in output, If I omit the above line

1
2
3
1963060099
Amit G.
  • 2,546
  • 2
  • 22
  • 30
Kanishk Mewal
  • 399
  • 2
  • 10
  • 4
    `NULL` is a legacy C integer constant, and it is advised to use `nullptr` in C++ instead. "I Know it can be fixed with" -> This is not a fix, this is the correct way to program. You are trying to access an unitialized variable (`third.next` is never assigned), which is undefined behaviour – Raildex Oct 24 '21 at 07:47
  • 1
    As you correctly noticed, `third.next` was not initialized to `NULL` before the fix. So `third.next` was derefenced, yielding to *undefined behavior*. The most probable behavior would be a segmentation fault, but here `third.next` happened to contain a memory address that was accessible and containing the number 1963060099. – prapin Oct 24 '21 at 07:55
  • 1
    One reason to invent C++ was to have the possibility to define automatic initialization for classes like `node`. That language facility is called "constructor" ;-). Exercise: What should `node`'s constructor do? ;-) – Peter - Reinstate Monica Oct 24 '21 at 09:23

2 Answers2

2

As described in the comment by prapin, third.next is not initialized. C++ has a zero-overhead rule. Automatically initializing a variable would violate this rule as the value might be initialized (a second time) later on or never even be used.

The value of third.next is just the data that happened to live in the same memory location as third.next does now. For this reason, it's recommended to always initialize your variables yourself.

StackOverflower
  • 526
  • 3
  • 14
2

It is better to initialize variables & it is better to use nullptr. Like that (See 1-3):

#include <iostream>

class node
{
public:
    int data = 0; // 1
    node* next = nullptr; // 2
};

void PrintList(node* n)
{
    while (n != nullptr) // 3
    {
        std::cout << n->data << std::endl;
        n = n->next;
    }
}
 
int main()
{
    node first, second, third;

    node* head = &first;
    node* tail = &third;

    first.data = 1;
    first.next = &second;

    second.data = 2;
    second.next = &third;

    third.data = 3;
    // third.next points to where?

    PrintList(head);
}

Additional note:

I would prefer to use the STL container std::list:

#include <list>
#include <iostream>

std::list<int> int_list;

void PrintList()
{
    for (auto i : int_list)
        std::cout << i << std::endl;
}

int main()
{
    int_list.push_back(1);
    int_list.push_back(2);
    int_list.push_back(3);

    PrintList();
}

Or in case of list of node objects:

#include <list>
#include <iostream>

class node
{
public:
    node(int data) : m_data{ data } {};
    int m_data = 0;
    // and maybe extra data-members
};

std::list<node> node_list;
 
void PrintList()
{
    for (auto i : node_list)
        std::cout << i.m_data << std::endl;
}   

int main()
{
    node_list.push_back(node(1));
    node_list.push_back(node(2));
    node_list.push_back(node(3));

    PrintList();
}
Amit G.
  • 2,546
  • 2
  • 22
  • 30