abba
abba

Reputation: 11

C++ How multi-dimensional arrays works behind the scenes

I am newbie in C++ and trying to understand one important thing. I have heard that all arrays are only pointer aliases and every action done by [] operator is converted to pointer dereference. See the example below (dynamic array).

auto **tab = new int*[2];
tab[0] = new int[2];
tab[1] = new int[2];

tab[0][0] = 1;
tab[0][1] = 2;
tab[1][0] = 3;
tab[1][1] = 4;

cout << "tab[0] address: " << &tab[0] << " with value: " << tab[0] << endl;
cout << "tab[1] address: " << &tab[1] << " with value: " << tab[1] << endl;
cout << "tab[0][0] address: " << &tab[0][0] << " with value: " << tab[0][0] << endl;
cout << "tab[0][1] address: " << &tab[0][1] << " with value: " << tab[0][1] << endl;
cout << "tab[1][0] address: " << &tab[1][0] << " with value: " << tab[1][0] << endl;
cout << "tab[1][1] address: " << &tab[1][1] << " with value: " << tab[1][1] << endl;

delete[] tab[0];
delete[] tab[1];
delete[] tab;

This is pretty simple program, which shows how pointer to pointer is represented in memory. It returns the following result:

tab[0] address: 0x7114d0 with value: 0x7114e0
tab[1] address: 0x7114d4 with value: 0x7114f0
tab[0][0] address: 0x7114e0 with value: 1
tab[0][1] address: 0x7114e4 with value: 2
tab[1][0] address: 0x7114f0 with value: 3
tab[1][1] address: 0x7114f4 with value: 4

Note: I fully understand how it works. I have two basic adresses, which points to the other second addresses. As a result dereferencing tab[0] returns memory address to the second dimension. Pseudocode:

*(0x7114d0) = 0x7114e0 -> 1

But the second example shows how static arrays works.

int tab[2][2] = {{1,2}, {3,4}};

cout << "tab[0] address: " << &tab[0] << " with value: " << tab[0] << endl;
cout << "tab[1] address: " << &tab[1] << " with value: " << tab[1] << endl;
cout << "tab[0][0] address: " << &tab[0][0] << " with value: " << tab[0][0] << endl;
cout << "tab[0][1] address: " << &tab[0][1] << " with value: " << tab[0][1] << endl;
cout << "tab[1][0] address: " << &tab[1][0] << " with value: " << tab[1][0] << endl;
cout << "tab[1][1] address: " << &tab[1][1] << " with value: " << tab[1][1] << endl;

Same as in the previous example I get results:

tab[0] address: 0x28fea0 with value: 0x28fea0
tab[1] address: 0x28fea8 with value: 0x28fea8
tab[0][0] address: 0x28fea0 with value: 1
tab[0][1] address: 0x28fea4 with value: 2
tab[1][0] address: 0x28fea8 with value: 3
tab[1][1] address: 0x28feac with value: 4

And in this point I have a huge problem how to understand this, bacause dereferencing 'tab[0]' returns the address of 'tab[0]' which also hold value(1)... Pseudocode

*(0x28fea0) = 0x28fea0 -> 1

And now how tu understand it? It seems that in memory static and dynamic multidimensional arrays are handle in two different ways. If arrays are in fact pointers how static arrays dereferencing works by the fact that tab[0] handle own address (pseudocode below)...

Upvotes: 1

Views: 154

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148890

2D arrays and arrays of pointers are different animals, even if their syntax is the same.

This is an array of pointers to arrays:

auto **tab = new int*[2];
tab[0] = new int[2];
tab[1] = new int[2];

tab is an array of pointers, each element of tab points to a row, but the rows are allocated independently of each others and are not (necessarily) contiguous. In theory they could even have different sizes, which is common for arrays of C-strings.

This is a 2D array:

int tab[2][2];

It is an array of arrays. Here the rows are required to have same size and are contiguously allocated: &tab[0][2] is required to be the same as &tab[1][0]

But is is completely independant of static or dynamic allocation. Here is a static array of pointers:

int row1[2] = { 0, 1};
int row2[2] = { 2, 3};
int *tab[] = { row1, row2 }; // row1 and row2 decay to pointers to their first element;

And here is a dynamically allocated 2D array:

typedef int iarr2[2];
iarr2* dyntab = new iarr2[2];

Upvotes: 1

Related Questions