Activity solution[a][b];
...
Activity **mother = solution;
I want to convert 2D array of objects to pointer-to-pointer. How can I do this;
I searched it on google. however I found only one dimension array example.
Activity solution[a][b];
...
Activity **mother = solution;
I want to convert 2D array of objects to pointer-to-pointer. How can I do this;
I searched it on google. however I found only one dimension array example.
Why? Is it because an interface expects a pointer to pointers?
If so, you'll need to create a new array that contains those pointers.
Why can't you just cast a 2D array of
T
toT**
? Well, because they have nothing to do with one another!You can cast a
T[a]
to aT*
because you get a pointer to the first element of the array.You can do this with 2D arrays as well, but if you have a
T[a][b]
then it decays to a(T[b])*
because a 2D array is not an array of pointers, it's an array of arrays.Not sure if you were looking for something like this. You should provide more details about what you want to achieve. They are fundamentally different types. One solution is to below.
For the record, if someone finds it useful:
The reason you can do this for one-dimensional arrays and not two-dimensional arrays has to do with the way in which the actual array elements are stored in memory. For one-dimensional arrays, all of the elements are stored consecutively, so the expression
array[i]
is equivalent to the expression*(array + i)
. As you can see, the array size is not needed to perform an array index operation. However, for two-dimensional arrays, the elements are stored in "row major" order, meaning that all of the elements in the zeroth row are stored first, followed by the elements in the first row, followed by the elements in the second row, etc. Therefore, the expressionarray[i][j]
is equivalent to*(array + (i * ROW_SIZE) + j)
, whereROW_SIZE
is the number of elements in each row. Therefore, the array's row size is needed to perform an array index operation, and casting the array variable to a pointer loses that information.This is c++! Everything is possible! But a this is c++ so it requires some level of understanding.
To that end let's start with a simple example of 2 1-dimensional arrays:
char firstName[4] = { 'J', 'o', 'n', '\0' }
andchar lastName[4] = { 'M', 'e', 'e', '\0' }
Let's look at a possible memory layout here:Given this memory layout if you were to do
cout << firstName << ' ' << lastName
you'd get:These arrays are really just a pointer to their first element! This illustrates Array to Pointer Decay, which you can read more about here: http://en.cppreference.com/w/cpp/language/array#Array-to-pointer_decay
Before we move on there's something important here to note,
char
s take up exactly 1-byte so the address of each subsequentchar
in the array will simply be the next address. That's leveraged by the Subscript Operator in this way:firstName[1]
is equivalent to*(firstName + 1)
. This is true forchar
s but is also true for any other type which takes up more than 1-byte. Let's take for example:short siArray = { 1, 2, 3, 4 }
, a possible memory layout ofsiArray
would look like:Even though
cout << siArray << ' ' << &(siArray[1])
will output:*(siArray + 1)
will still index the same element ofsiArray
assiArray[1]
. This is because when doing pointer arithmetic c++ considers the type of the address being operated on, thus incrementing ashort*
will actually increase the address bysizeof(short)
. You can read more about pointer arithmetic here: http://en.cppreference.com/w/cpp/language/operator_arithmeticLastly let's look at how c++ stores 2-dimensional arrays. Given:
char name[2][4] = { { 'J', 'o', 'n', '\0' }, { 'M', 'e', 'e', '\0' } }
a possible memory layout would be:Since we know an 1-dimensional array value is really just a pointer, we can see from this memory layout that
name[0]
is not a pointer, it's just the first character of the first array. Thusname
does not contain 2 1-dimensional array pointers, but contains the contents of the 2 arrays. (Incidentally on a 32-bit machine not storing the pointers saves 8-bytes of memory, which is pretty substantial for an 8-byte 2-dimensional array.) Thus trying to treatname
as achar**
would try to use the characters as a pointer.Having understood this we really just need to avoid using c++'s pointer arithmetic to find dereference the value. To do that we'll need to work with a
char*
so that adding 1 is really just adding 1. So for example:Live Example
Note that in this example even though I reference
si2DArray
thoughtpsi2DPointer
I'm still using information fromsi2DArray
to do the indexing, namely:size(si2DArray)
size(*si2DArray)
sizeof(*si2DArray)
sizeof(**si2DArray)
You can thus see that the loss of information from converting from an array to a pointer is substantial. You may be tempted to preserve the element type, thereby also simplifying the pointer arithmetic. It's worthwhile to note that only a conversion to
char*
is considered defined behavior byreinterpret_cast
: http://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasingYou can't. They are fundamentally different types.
A mere conversion won't help you here. There's no compatibility of any kind between 2D array type and pointer-to-pointer type. Such conversion would make no sense.
If you really really need to do that, you have to introduce an extra intermediate "row index" array, which will bridge the gap between 2D array semantics and pointer-to-pointer semantics
Now accessing
mother[i][j]
will give you access tosolution[i][j]
.