I'm asking this because my program have two functions to multiply matrices, they multiply only 4x4 and 4x1 matrices. The headers are:
double** mult4x1(double **m1, double **m2);
double** mult4x4(double **m1, double **m2);
They do m1*m2 and return it in a **double, below is a snippet of 4x4 multiplication.
double** mult4x4(double **m1, double **m2){
double** result = (double**) malloc(sizeof(double)*4);
for (int i = 0; i < 4; i++) {
result[i] = (double*) malloc(sizeof(double)*4);
}
...multiply...
return result;
}
The difference between mult4x1 and mult4x4 are only in the indexes used inside them.
I have these 3 matrices:
double m1[4][4] = {
{2, 3, 5, 6},
{9, 8, 1, 7},
{5, 4, 3, 1},
{7, 6, 1, 2}
};
double m2[4][4] = {
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1}
};
double m3[4][1] = {
{2},
{3},
{3},
{1}
};
Trying to multiply these matrices an error occurs.
double** test = mult4x4(m1, m2);
double** test2 = mult4x1(identity4x4(), m3);
//identity4x4() creates a 4x4 identity matrix - double** identity4x4();
Yields:
error: cannot convert
double (*)[4]' to
double*' for argument1' to
double* mult4x4(double*, double*)'error: cannot convert
double (*)[1]' to
double*' for argument2' to
double* mult4x1(double*, double*)'
Isn't double[][] supposed to be equal to **double? An array of arrays of double. Any clarifications, misconceptions and errors are welcome.
No. A multidimensional array is a single block of memory.
An array is treated as a pointer that points to the first element of the array. 2D array is NOT equivalent to a double pointer! 2D array is "equivalent" to a "pointer to row".
In case it isn't clear, your array cannot be of double length. It's undefined behavior. This is because a double is not an integer, but a rational number that could be an integer.
No.
A double**
is a pointer to a pointer to a double (double*
).
So actually it should be created like this (note the extra * in the first malloc sizeof()):
double** result = (double**) malloc(sizeof(double*)*4); for (int i = 0; i < 4; i++) { result[i] = (double*) malloc(sizeof(double)*4); }
So in memory it would look like this:
[] -> { d,d,d,d } [] -> { d,d,d,d } [] -> { d,d,d,d } [] -> { d,d,d,d }
There are 4 buffers that hold 4 doubles, but are not continuous.
While your double[4][4] is a continuous buffer in memory, like this:
{ { d,d,d,d } { d,d,d,d } {d,d,d,d} {d,d,d,d} }
Although both double[N][M]
and double**
let you deal with 2D arrays, the two are definitely not equivalent: the former represents a 2D array of double
s, while the later represents a pointer to pointer to double, which can be interpreted (with the help of convenient square bracket syntax of C/C++) as an array of pointers to double
, or as an array of arrays of double
.
The double[N][M]
represents 2D arrays of "rectangular" shape, while double**
lets you build "free-form" (jagged) arrays by allocating different amounts of memory to each row of your matrix.
The difference to the compiler is that given double[N][M]
and a pair of integers {r,c}
it can compute the location of the element by computing the offset from the origin of the array, without reading anything from the memory. Given a double**
, however, the compiler must compute the address of the pointer to a row, read that pointer, and only then compute the address of the target element. Because of this difference, the two are not interchangeable.
There is no type [][]
. What you have is in fact m2
which is an array of arrays of size 4 of type double and m1
which is an array of arrays of size 1. An array of arrays of size 4 is not equivalent to double pointer.
Well I hope I will not turn out stupid here but the notation double [][]
is also used when you are addressing a continuous block of memory, while double**
is not necessarily continuous.
I think that is the reason behind the error. Even though you can use the same semantics to access values, they are actually different types.
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