I have a function that takes a pointer to a floating point array. Based on other conditions, I know that pointer is actually pointing to a 2x2 OR 3x3 matrix. (in fact the memory was initially allocated as such, e.g. float M[2][2] ) The important thing is I want to make this determination in the function body, not as the function argument.
void calcMatrix( int face, float * matrixReturnAsArray ) { // Here, I would much rather work in natural matrix notation if( is2x2 ) { // ### cast matrixReturnAsArray to somethingAsMatrix[2][2] somethingAsMatrix[0][1] = 2.002; // etc.. } else if(is3x3) { //etc... } }
I am aware that I could use templates and other techniques to better address this problem. My question is really about how to make such a cast at the ### comment. Working in C++.
Creating Multidimensional Arrays You can create a multidimensional array by creating a 2-D matrix first, and then extending it. For example, first define a 3-by-3 matrix as the first page in a 3-D array. Now add a second page. To do this, assign another 3-by-3 matrix to the index value 2 in the third dimension.
In Python, Multidimensional Array can be implemented by fitting in a list function inside another list function, which is basically a nesting operation for the list function. Here, a list can have a number of values of any data type that are segregated by a delimiter like a comma.
float (*somethingAsMatrix)[2] = (float (*)[2]) matrixReturnAsArray;
float *
could point to the first element of an array of floats, and ought to be reinterpret_castable to that array type. And the result of that cast could point to the first element of a float [][]
and so should be reinterpret_castable to that type, and so on. You ought to be able to compose such casts and just directly do
float (&arr)[2][2] = *reinterpret_cast<float (*)[2][2]>(matrixReturnAsArray);
An argument of the type float **
is not the same and should not be used this way.
To avoid undefined behavior the pointer must originate from an actual multi-dimensional array, and if the float*
is used directly you cannot access more than the first row of the multi-dimensional matrix.
void foo(float *f) { f[3] = 10.; float (&arr)[2][2] = *reinterpret_cast<float (*)[2][2]>(f); arr[1][1] = 10.; } void main() { float a[2][2]; foo(&a[0][0]); // f[3] = 10.; is undefined behavior, arr[1][1] = 10. is well defined float b[4]; foo(&b[0]); // f[3] = 10.; is well-defined behavior, arr[1][1] = 10. is undefined }
Given float arr[2][2];
nothing guarantees that &arr[0][1] + 1
is the same as &arr[1][0]
, as far as I have been able to determine. So although you can use a single dimensional array as a multi-dimensional array by doing f[i*width + j]
you cannot treat a multi-dimensional array like a single dimensional array.
It's better to use C++'s compile-time type-safety instead of just relying on not accidentally passing the wrong thing or performing the wrong reinterpret_cast. To get type-safety using raw-arrays you should use references to the raw array type you want:
void foo(float (&f)[2][2]) {} void foo(float (&f)[3][3]) {}
If you want to pass arrays by value you can't use raw arrays and should instead use something like std::array:
void foo(std::array<std::array<float,2>,2> f) {} void foo(std::array<std::array<float,3>,3> f) {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With