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 int
s". 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
Replace Multiple Spaces with One Space in a String
When Is a Vtable Created in C++
Template Specialization Based on Inherit Class
Avx2: Computing Dot Product of 512 Float Arrays
C++ Format MACro/Inline Ostringstream
Boost-Python How to Pass a C++ Class Instance to a Python Class
Convert Eigen Matrix to C Array
How to Create Std::Array with Initialization List Without Providing Size Directly
Memory Allocation Profiling in C++
Problems Using Member Function as Custom Deleter with Std::Shared_Ptr
How to Check If a Function Exists in C/C++
Is Boost Shared_Ptr <Xxx> Thread Safe
Can't Find Windows Forms Application for C++
Safer But Easy-To-Use and Flexible C++ Alternative to Sscanf()