Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding these Pointer Statements - Diagram

Tags:

c++

pointers

I am trying to understand the following 3 code statements involving pointers (through image diagrams). If you can explain it without images that would also work

1- myobj *ptra = new myobj();
2- myobj *ptrb = new myobj[2]();
3- myobj **ptrc = new *myobj();

Here is my understanding , please correct me if I am wrong. Also the addresses in the image are totally imaginary (I know they don't make sense). My major concerns of understanding are basically with statement 2 and statement 3.

Statement 1 : ptra (which is some address on the stack) points to an address on the heap

Statement 2: ptra (which is some address on the stack) points to one address which has 2 parts ? Is that correct ?

enter image description here

like image 969
Murphy316 Avatar asked Dec 10 '25 14:12

Murphy316


1 Answers

Your understanding is somewhat correct, though it seems like you mix too many things together and your diagram is missing details. Here is how I'd draw it for a few of the most simple cases...

Let's start from a simple case and take operator new out of the picture:

#include <cstdio>

struct myobj {
    int v;
};

int main()
{
    myobj obj[2];

    obj[0].v = 1;
    obj[1].v = 2;

    myobj *ptra = &obj[0];
    myobj *ptrb = &obj[1];
    myobj **ptrc = &ptrb;

    printf("obj size is: %lu\n", sizeof(myobj));
    printf("pointer size: %lu\n", sizeof(void *));

    printf("obj[0] address: %p\n", (void *)&obj[0]);
    printf("obj[1] address: %p\n", (void *)&obj[1]);
    printf("ptra address is %p, it points to %p\n", (void *)&ptra, (void *)ptra);
    printf("ptrb address is %p, it points to %p\n", (void *)&ptrb, (void *)ptrb);
    printf("ptrc address is %p, it points to %p\n", (void *)&ptrc, (void *)ptrc);
}

The above program will output something like this:

$ g++ -Wall -pedantic -o test ./test.cpp 
$ ./test 
obj size is: 4
pointer size: 8
obj[0] address: 0x7fff5b73dbc0
obj[1] address: 0x7fff5b73dbc4
ptra address is 0x7fff5b73dbb8, it points to 0x7fff5b73dbc0
ptrb address is 0x7fff5b73dbb0, it points to 0x7fff5b73dbc4
ptrc address is 0x7fff5b73dba8, it points to 0x7fff5b73dbb0

Which corresponds to the following simple layout in memory:

simple data layout

So what's different from your drawing? Addresses of pointers and objects. If the pointer itself is placed at address 0, then the next pointer cannot be placed at address 1 simply because a pointer itself takes more space, and so other data can only be placed at 0 + sizeof(void*) address. For objects, the next address is greater by at least the size of the object itself (i.e. sizeof(myobj)).

When dynamic allocation gets involved, the picture changes a bit. For example, when operator "new" is used to allocate objects like this:

myobj *ptra = new myobj();
myobj *ptrb = new myobj();
myobj **ptrc = &ptrb;

... you can think of a memory layout like this:

dynamic memory layout

Now, a pointer to another pointer (**) is nothing but a pointer that points to the first of one or more pointers that point to object(s). Easy, right? Any you can have pointer to a pointer to a pointer... Anyway, with a dynamically allocated pointer to pointers, like this:

myobj *ptra = new myobj();
myobj *ptrb = new myobj();
myobj **ptrc = new myobj*[2];
ptrc[0] = ptra;
ptrc[1] = ptrb;

The memory layout could look like this:

with pointer to pointer(s)

By the way, you have an error in your line #3 here - myobj **ptrc = new *myobj();. It should be myobj **ptrc = new myobj*();.

To address your later questions, below is a diagram depicting the result of myobj *ptrb = new myobj[2](); expression where you have a pointer that points to two objects allocated dynamically. The pointer itself points to the first object out of two allocated:

myobj *ptrb = new myobj[2]();

And one more time about pointers to pointers so that you can see the difference. Consider the following code:

struct myobj {
    int v;
};

int main()
{
    myobj *ptra = new myobj[2]();
    myobj *ptrb = new myobj[4]();
    myobj **ptrc = new myobj*[2];

    ptrc[0] = ptra;
    ptrc[1] = ptrb;

    ptrc[0][0].v = 1;
    ptrc[0][1].v = 2;
    ptrc[1][0].v = 3;
    ptrc[1][1].v = 4;
    ptrc[1][2].v = 5;
    ptrc[1][3].v = 6;
}

It will create the following layout:

enter image description here

As you can see, the stack contains three pointers (they are also objects) that are not dynamically allocated. This is a result of declaration:

myobj *ptra;
myobj *ptrb;
myobj **ptrc;

Then, three different things are allocated with "new":

  1. Two objects of type myobj are allocated with expression new myobj[2](), the address to the first of those objects is stored in pointer ptra.
  2. Four objects of type myobj are allocated with expression new myobj[4](), the result of that expression is address of the first out of four objects, and it is stored in pointer "ptrb".
  3. Two pointers are allocated with with expression new myobj*[2]. The result of that expression is an address of the first out of two pointers. That address is stored in variable ptrc.

Now, those two allocated pointers (in "Block C") point "nowhere". So just for the sake of example we make them point to the same objects as ptra and ptrb are pointing by copying pointers "by value":

ptrc[0] = ptra;
ptrc[1] = ptrb;

That easy!


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!