mrei
mrei

Reputation: 121

Understanding C++ code with 'new' and pointers

This might be simple but I am getting trouble understanding it.

An excerpt of the code I am trying to understand:

SomeStruct ***namestruct = new SomeStruct **[intVariable];
           //Three level pointer and... two level pointer?
                                 //or product and pointer?

for(int i=0; i < intVariable; i++)
  namestruct[i] = new SomeStruct *[2]; //creates the same structure time 2?

for(int i=0; i < intVariable; i++) {  // just initialization of a
  namestruct[i][0] = NULL;            // matrix like structure?
  namestruct[i][1] = NULL;
}

The code works, but I need to understand why the programmer did what it's done.

How can I assign the address from another instance of the structure passed as an address through a function? Example:

void function(SomeStruct **othername);

int main()
{
  SomeStruct *othername;
  function(&othername);
  return 0;
}

void function(SomeStruct **othername)
{
  SomeStruct ***namestruct = new SomeStruct **[intVariable];
  for(int i=0; i < intVariable; i++)
    namestruct[i] = new SomeStruct *[2];

  for(int i=0; i < intVariable; i++) {  
    namestruct[i][0] = NULL;
    namestruct[i][1] = NULL;
  }

  // This is what I want to do
  ...
  namestruct[x][0] = &othername[i]; // Error cannot convert SomeStruct**
                                      // to SomeStruct* in assignment
  ...
}

Thanks for you help! The questions are in the code itself and the method to assign the address of the otherstruct to namestruct.

Upvotes: 0

Views: 123

Answers (2)

AlexanderBrevig
AlexanderBrevig

Reputation: 1987

I will make the assumption that this is in fact your question:

How can I assign the address from another instance of the structure passed as an address through a function?

Short answer:

namestruct[x][0] = othername[i]; //if othername is SomeStruct**

Long answer:

SomeStruct ***namestruct = new SomeStruct **[intVariable];
// namestruct is a three level pointer, that means you will need three levels
// of dereferencing to get to an actual value
// the use of [] notation is the same as a pointer, except you can allocate space
// in memory. You may recognize the difference between 
// char *someString; //uninitialized, _points_ to 1 available bytes
// char someString[12]; //uninitialized _points_ to 12 available bytes
// now, in order to get a value from either of these _pointers_ you use [] 
// as a way of dereferencing

// the way array dereferencing works is simply that you multiply the sizeof(obj)
// with the index, and offset your pointer that many bytes
// such that someString[3] == *(someString + sizeof(char)*3)

// this means, namestruct is now an 'array' i.e it has memory allocated 
// for intVariable instances, those locations are typed to be SomeStruct **


for(int i=0; i < intVariable; i++)
    namestruct[i] = new SomeStruct *[2]; // since we've learned that * and [] is 
    // almost the same thing, the type SomeStruct *[2] is the same that we expected here
    // which was SomeStruct **
    // namestruct[i][x] will be typed to SomeStruct *, because we dereference two layers
    // from the original three with the use of the array indexer

for(int i=0; i < intVariable; i++) {  // this is initializing the two pointers generated
    namestruct[i][0] = NULL;          // in the loop above with new SomeStruct *[2];
    namestruct[i][1] = NULL;          // to 0 or NULL
}

// You can assign any SomeStruct* to a namestruct[x][y] deref
// because the types will match.

Upvotes: 2

MooseBoys
MooseBoys

Reputation: 6793

The following illustrates the state of your pointer arrays prior to the problematic assignment:

[SomeStruct***("namestruct")]
    |
    V
    [0:SomeStruct**][1:SomeStruct**][2:SomeStruct**][ ...
           |               |               |
           |               |               V
           |               |               [0:SomeStruct*][1:SomeStruct*]
           |               |                   (NULL)         (NULL)
           |               V
           |               [0:SomeStruct*][1:SomeStruct*]
           |                   (NULL)         (NULL)
           V
           [0:SomeStruct*][1:SomeStruct*]
               (NULL)         (NULL)

[SomeStruct**("othername, function scope")]
     |
     V
     [0:SomeStruct*("othername, main scope")]

At this point, if you want to assign the SomeStruct* at one of the leaf nodes to point to the same SomeStruct as othername in the main scope, you would do namestruct[x][0] = *othername. Note that you can eliminate the extra level of pointer if this is, in fact, your goal:

SomeStruct *othername;
function(othername);
//...
void function(SomeStruct *othername)
{
   //...
   namestruct[x][0] = othername;

Upvotes: 3

Related Questions