Q:

Understanding the operation of pointers in C++

I have been trying to understand how pointers in C++ work and I have a few doubts that I was hoping somebody here would help me with.
Say I have a structure as follows:
struct node
{
    int val;
    node *n1;
    node **n2;
};

Also I have a function as follows:
void insertVal(node *&head, node *&last, int num)

My questions:

What does n2 point to? What is the difference between using '*' and '**'?
In the function what does *& mean? I have noticed that in a linked list implementation for insert (in a tutorial I saw) '*&' was used instead of just '*' why is this the case?

My apologies if this question is silly but I am struggling to understand this. Thanks.
EDIT: I simplified the structure just to understand what ** means. The code is here: http://www.sanfoundry.com/cpp-program-implement-b-tree/. Somebody mentioned that ** refers to an array of nodes and I think that is the case here.

A:

What does n2 point to?

There is no way to answer that without seeing the actual code that uses it.  But, if I had to guess, it is probably a pointer to a dynamic array of child node pointers, for example:
node *n = new node;
n->val = ...;
n->n1 = ...;
n->n2 = new node*[5];
n->n2[0] = new node;
n->n2[1] = new node;
n->n2[2] = new node;
n->n2[3] = new node;
n->n2[4] = new node;

What is the difference between using '*' and '**'?

A pointer to a node versus a pointer to a pointer to a node, eg:
node n;
node *pn = &n;
node **ppn = &pn;

In the function what does *& point to?

It is a reference (&) to a pointer variable (*).  It might be easier to read if you tweak the whitespace around the parameters:
void insertVal(node* &head, node* &last, int num)

I have noticed that in a linked list implementation for insert (in a tutorial I saw) '*&' was used instead of just '*' why is this the case?

A reference is used so that the caller's variable that is being referred to can be modified by the function, eg:
void insertVal(node* &head, node* &last, int num)
{
    ...
    // head and last are passed by reference, so any
    // changes made here are reflected in the caller...
    head = ...;
    last = ...;
    ...
}

node *head = ...;
node *last = ...;
...
insertVal(head, last, ...);
// head and last contain new values here ...

Otherwise, without & (or a second *), the original pointer is just passed by value as a copy, and any alterations to that copy does not get reflected in the caller's variable:
void insertVal(node* head, node* last, int num)
{
    ...
    // head and last are passed by value, so any changes
    // made here are not reflected in the caller...
    head = ...;
    last = ...;
    ...
}

node *head = ...;
node *last = ...;
...
insertVal(head, last, ...);
// head and last still have their original values here ...

