How to Cast Simple Pointer to a Multidimensional-Array of Fixed Size

How to cast simple pointer to a multidimensional-array of fixed size?

float (*somethingAsMatrix)[2] = (float (*)[2]) matrixReturnAsArray;

Casting pointer to multidimensional array

While it's normally dangerous to do so, you can use reinterpret_cast should you really want to:

f2( reinterpret_cast<float(*)[100][100]> (p) );

Create a pointer to two-dimensional array

Here you wanna make a pointer to the first element of the array

uint8_t (*matrix_ptr)[20] = l_matrix;

With typedef, this looks cleaner

typedef uint8_t array_of_20_uint8_t[20];
array_of_20_uint8_t *matrix_ptr = l_matrix;

Then you can enjoy life again :)

matrix_ptr[0][1] = ...;

Beware of the pointer/array world in C, much confusion is around this.


Edit

Reviewing some of the other answers here, because the comment fields are too short to do there. Multiple alternatives were proposed, but it wasn't shown how they behave. Here is how they do

uint8_t (*matrix_ptr)[][20] = l_matrix;

If you fix the error and add the address-of operator & like in the following snippet

uint8_t (*matrix_ptr)[][20] = &l_matrix;

Then that one creates a pointer to an incomplete array type of elements of type array of 20 uint8_t. Because the pointer is to an array of arrays, you have to access it with

(*matrix_ptr)[0][1] = ...;

And because it's a pointer to an incomplete array, you cannot do as a shortcut

matrix_ptr[0][0][1] = ...;

Because indexing requires the element type's size to be known (indexing implies an addition of an integer to the pointer, so it won't work with incomplete types). Note that this only works in C, because T[] and T[N] are compatible types. C++ does not have a concept of compatible types, and so it will reject that code, because T[] and T[10] are different types.


The following alternative doesn't work at all, because the element type of the array, when you view it as a one-dimensional array, is not uint8_t, but uint8_t[20]

uint8_t *matrix_ptr = l_matrix; // fail

The following is a good alternative

uint8_t (*matrix_ptr)[10][20] = &l_matrix;

You access it with

(*matrix_ptr)[0][1] = ...;
matrix_ptr[0][0][1] = ...; // also possible now

It has the benefit that it preserves the outer dimension's size. So you can apply sizeof on it

sizeof (*matrix_ptr) == sizeof(uint8_t) * 10 * 20

There is one other answer that makes use of the fact that items in an array are contiguously stored

uint8_t *matrix_ptr = l_matrix[0];

Now, that formally only allows you to access the elements of the first element of the two dimensional array. That is, the following condition hold

matrix_ptr[0] = ...; // valid
matrix_ptr[19] = ...; // valid

matrix_ptr[20] = ...; // undefined behavior
matrix_ptr[10*20-1] = ...; // undefined behavior

You will notice it probably works up to 10*20-1, but if you throw on alias analysis and other aggressive optimizations, some compiler could make an assumption that may break that code. Having said that, i've never encountered a compiler that fails on it (but then again, i've not used that technique in real code), and even the C FAQ has that technique contained (with a warning about its UB'ness), and if you cannot change the array type, this is a last option to save you :)

How to convert fixed size array to pointer on pointer array

Array with two dimensions and a pointer to another pointer are not the same things. Why do you need to use mat in different ways for two different functions such as double mat[N][N] in the function getCofactor() and double **mat in the determinant() function ? Since you know what is the value of N variable, you can use it as double mat[N][N] in the determinant() function as well.

double determinant(double mat[N][N], int n)
{
double D = 0; // Initialize result

// Base case : if matrix contains single element
if (n == 1)
return mat[0][0];

double temp[N][N]; // To store cofactors

int sign = 1; // To store sign multiplier

// Iterate for each element of first row
for (int f = 0; f < n; f++)
{
// Getting Cofactor of mat[0][f]
getCofactor(mat, temp, 0, f, n); //ERORRRRRRRRRRR
D += sign * mat[0][f] * determinant(temp, n - 1);

// terms are to be added with alternate sign
sign = -sign;
}

return D;
}

Once you make the change I mentioned, your error will be fixed. Hope it helps.

Addition: I want to correct something which can cause a misunderstanding;

Array with two dimensions and a pointer to another pointer are not the
same things.

Please note that you can have something which acts like a multidimensional array with pointers. But the way how they are occupying and storing in the RAM is not same. Note that, a multidimensional array is a single block of memory. To understand it better, check the following question;

Why can't we use double pointer to represent two dimensional arrays?

C - casting of a multidimensional array

int m[10][20];
int (*pm)[20] = m; // [10] disappears, but [20] remains

int t[10][20][30];
int (*pt)[20][30] = m; // [10] disappears, but [20][30] remain

This is not a "cast" though. Cast is an explicit type conversion. In the above examples the conversion is implicit.

Not also that the pointer type remains dependent on all array dimensions except the very first one. It is not possible to have a completely "dimensionless" pointer type that would work in this context, i.e. an int ** pointer will not work with a built-in 2D array. Neither will an int *** pointer with a built-in 3D array.

Pointer casting with unknown array size in C++

First I suggest to don't use runtime size for array in C/C++, except you using STL vector as an array. so instead of:

int i = 5;

you must use:

const int i = 5;

except you use Vector that is safe and better than intrinsic arrays.

how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time? Is it somehow possible?

If we talk about C intrinsic array, It is not possible!

why it is not possible?
because C/C++ compiler not aware of your the array size, borders,.... so if you cast your 2d array to 1d array, it is possible. it is the reason that tab2 array can access to first 5th element of your array. really C/C++ compiler cannot distinguish the different of

int a[3][3]

with

int a[3*3]

so You must be aware of at least one dimension of your array:

int main() {
const int i = 3,j = 4;

int tab1[i][j] = {1,2,3,4,5,6,7,8,9,10,11};

//cast to void pointer
void *p = (void *)tab1;

auto a = (int (*)[i][12/i])p;
return 0;
}

In the above example, I aware about i and total count(12) and I calculate the second dimension.
I use auto keyword that very easily inferred the data type.

How to allocate a 2D array of pointers in C++

By the letter of the law, here's how to do it:

// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
array2d[i] = new (int*)[cols];
}

// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
array2d[i][j] = NULL;
}
}

Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order.

However, more frequently in C++ you'd create a class that internally managed a 1D array of pointers and overload the function call operator to provide 2D indexing. That way you're really have a contiguous array of pointers, rather than an array of arrays of pointers.

Casting Back to a 2-Dimensional Array

foo(reinterpret_cast<int* [3]>(bar()))

is not the same as

foo(reinterpret_cast<int (*) [3]>(bar()))

The former is casting bar to an array of 3 "int pointers".

The latter is casting bar to a pointer to an array of "3 ints". That's very different.

As to why you can't use int[][3] as a type in reinterpret_cast, I am not certain why that is the case. A language lawyer would be able to answer that.



Related Topics



Leave a reply



Submit