0

My teacher showed me this way of casting a 1D dynamic array to a 2D array
to use the fancy arr[i][j] syntax.

using myarr = int(*)[mat_size][mat_size];
int * data = new int[mat_size * mat_size];
myarr arr = (myarr)data;

Now it is possible to access element at pos [i][j] with

(*arr)[i][j]

instead of

data[i * mat_size + j].

Unfortunately I don't understand what's happening in this solution. Can someone please explain?

P. S. The solution works, but I don't understand it. I don't get why the myarr arr points at the data variable, not at the actual data in memory. Wouldn't it be so, if we did myarr arr = (myarr)&data ? Also I googled, and couldn't find any similar solution. Is it bad to do it this way? Why nobody does this?

  • Supplement your formal education with these [C++ books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Ron Feb 23 '18 at 19:43
  • Your teacher should teach you how to do this properly with `std::vector` – Chad Feb 23 '18 at 19:50
  • What is the problem? Won't compile? Compiles with warning? Compiles, no warnings, but doesn't behave correctly? – user4581301 Feb 23 '18 at 20:01
  • Unrelated: When I encounter something like this, I stick with `data[i * mat_size + j]`, but wrap it all up in a helper class like this one: https://isocpp.org/wiki/faq/operator-overloading#matrix-subscript-op – user4581301 Feb 23 '18 at 20:03

1 Answers1

0

In your first line,

using myarr = int(*)[mat_size][mat_size];

You're simply declaring a type: myarr is a custom type representing a pointer to a 2D array of int values. The using here is similar to typedef if you've worked with any older versions of C++.

Then,

int* data = new int[mat_size * mat_size];

declares a 1-dimensional pointer. In memory, this is a single series of values.

Next,

myarr arr = (myarr)data;

creates a new variable of type myarr - also a simple pointer - and points it to the address of the original array pointer. The difference with this pointer is that, when dereferenced the first time, it's an array type; thus its dereferencing syntax following the first dereference is different: as a 2-dimensional array, you use two pairs of brackets.

Notice, then, that this second array variable, in essence, still accesses a 1-dimensional array in the memory. In the first reference statement you have,

(*arr)[i][j]

To properly index into the array, C++ compiles the bracket syntax so that it'll automatically multiply the first index by the number of items in a single row. This was defined as part of your myarr, and was declared to be mat_size. Then, after this, it'll automatically add the second index.

(p.s. also don't get confused by the *arr part - the extra * is there because the myarr arr variable points to the data variable, not to the actual data array itself.)

Then, in your second statement,

data[i * mat_size + j]

you're using the original pointer, which has a nice bracket dereferencing syntax, but only dereferences as a 1-dimensional array. Because of this, you have to do the indexing yourself, manually multiplying the mat_size by the first index (i), and then manually adding the second (j).

Hope this helps!

Codesmith
  • 5,779
  • 5
  • 38
  • 50
  • Thank you for your reply. I don't understand why the `myarr arr` points at the `data` variable, not at the actual data. Wouldn't it be so, if we did `myarr arr = (myarr)&data` ? – Serge Petrenko Feb 24 '18 at 09:20