Pepperwork
Pepperwork

Reputation: 105

c++: understanding dynamic arrays

I am trying to understang a dynamic array. In this case - an array of pointers.

This program is Ok to me - it is working, everything is fine.

What troubles me is how the array is organized in the heap.

Let us launch it, that will be our example:

pn 00456878
pn[0] 003AFB90
pn[1] 003AFB80
pn[2] 003AFB70

Will you be so kind as to help me understand three matters:

1) Why the address of pn[0] is higher than that of pn[2]? I seemed to have assigned pn[0] before pn[1] and pn[2]?

2) I allocated memory in the heap for 3 elements of sizeof(POINT). sizeof(POINT) = 8. 003AFB70 + 8 = 3AFB78. Why the next element is 003AFB80?

3) I have formed an opinion that an array in the heap looks as follows:

pn->pn[0]
    pn[1]
    pn[2]

pn is a base address. The address of pn[0] = base address + 0. Judging from what I can see here we can conclude that there is a gap between a base address and the first element. Is it for some auxiliarry data or what is it for?

Thank you in advance.

My code is:

#include "stdafx.h"
#include <iostream>
using namespace std;
struct POINT 
{
    int x; 
    int y;
};

POINT ** pn;
POINT ** tmp;


int _tmain(int argc, _TCHAR* argv[])
{
    int counter = 3;
    POINT p_tmp;
    cout << "sizeof(POINT): " << sizeof(POINT) << endl;
    pn = new POINT * [counter];

    POINT a = {0, 0};
    POINT b = {1, 1};
    POINT c = {2, 2};

    pn[0] = &a;
    pn[1] = &b;
    pn[2] = &c;
    cout << "pn "<< pn << endl;

    cout << "pn[0] "<< pn[0] << endl;
    cout << "pn[1] "<< pn[1] << endl;
    cout << "pn[2] "<< pn[2] << endl;
    cin.get();

    POINT m = * pn[0];
    POINT n = * pn[1];
    POINT k = * pn[2];

    cout << m.x << ","<<m.y<< endl;
    cout << n.x << ","<<n.y<< endl;
    cout << k.x << ","<<k.y<< endl;
    cin.get();

    tmp = new POINT * [counter];
    memcpy(tmp, pn, (counter  * sizeof(POINT)));
    for (int i = 0; i < counter; i++)
    {
        cout << "tmp[" << i << "] "<< tmp[i] << endl;
    }
    cin.get();
    delete[] pn;
    pn = tmp;

    m = * pn[0];
    n = * pn[1];
    k = * pn[2];

    cout << m.x << ","<<m.y<< endl;
    cout << n.x << ","<<n.y<< endl;
    cout << k.x << ","<<k.y<< endl;
    cin.get();
    return 0;
}

Upvotes: 0

Views: 158

Answers (1)

user703016
user703016

Reputation: 37955

Your confusion arises from the fact that your array contains POINT*s and not POINTs.

Why the address of pn[0] is higher than that of pn[2]? I seemed to have assigned pn[0] before pn[1] and pn[2]?

It's not the address of pn[0] that you are printing, it's its value. The address of pn[0] is denoted by &pn[0].

POINT a = {0, 0};
POINT b = {1, 1};
POINT c = {2, 2};

pn[0] = &a;
pn[1] = &b;
pn[2] = &c;

Here you put in pn the addresses of a, b and c, which are POINTS you declared on the stack. The stack grows from upper addresses to lower addresses, therefore &a > &b > &c.

I allocated memory in the heap for 3 elements of sizeof(POINT). sizeof(POINT) = 8. 003AFB70 + 8 = 3AFB78. Why the next element is 003AFB80?

No, you allocated memory in the heap for 3 elements of sizeof(POINT*) (pointer to POINT, which happen to also be 8 bytes). You allocated an array of three pointers on the heap, but the pointees are on the stack.

In the end, your array looks like this:

(some address) pn-> (00456878) pn[0]-> (003AFB90) a
                    (00456880) pn[1]-> (003AFB80) b
                    (00456888) pn[2]-> (003AFB70) c

The pointer pn is static memory, but points to 3 pointers on the heap that point back to 3 elements on the stack.


If you wanted to have everything on the heap, you'd do it like this:

Point **pn = new POINT*[counter];

for (int i = 0; i < counter; ++i)
    pn[i] = new POINT;

In this layout, the pointer pn is in static memory, but points to 3 pointers on the heap that point to 3 elements on the heap.

Upvotes: 4

Related Questions