I didn’t want to have to change the header of the function findDet()
, it is possible to transform my variable of type double A[3][3]
in double **A
, before passing as parameter to my function?
Your type variable double A[3][3]
is the kind you declared, double[3][3]
, what your compiler can tell you. It’s a pointer and occupies what occupies a double*
on your platform. Say 8 bytes for an x64 build.
Your type variable double **A
would be best represented as double** A
, and is like double**
. It is a pointer and occupies what occupies a POINTER to double*
, the same 8 bytes in x64.
If you’re starting to program in this language, maybe you should declare things as they are. This is because it facilitates understanding and visualization and also helps to interpret compiler messages.
When you declare double** A
is declaring A
. A name. And declaring A
as a variable of a type, double**
.
If A
is double**
then *A
is double*
, and **A
is double
. This is the result of the operator *
in C, the one dereference Operator or indirect Operator. This is a consequence of the statement and not the statement.
If I can do this transformation, my function should run smoothly, right?
No. What is missing in your case is the size. You need to pass the size. C doesn’t even have matrices like FORTRAN. There are only scalar and vector types. And vectors are represented by base + displacement. Their model lacks displacement. For "matrices" there are vector vectors and vector vectors of vectors and so on.
An example of such pointers and the transformation
double A[3][3];
// agora uma "hierarquia"
double um_double = 42.;
double* pD = &um_double;
double** B = &pD;
This is a minimal representation of things as stated, A and B. To make it clear what is what it is like to declare and use pointers for these things:
// um ponteiro para A
double (*pA)[3][3] = &A;
// um ponteiro para B
double*** pB = &B;
And using it to access A[0][0]
or um_double
:
A[0][0] = 42.42; // um exemplo
A[2][2] = 84.84;
// usando os ponteiros para acessar os dados
printf("A[0][0] = %f (usando o ponteiro\n", (*pA)[0][0]);
printf("Usando B para acessar o valor = %f\n", ***pB);
that shows
A[0][0] = 42.420000 (usando o ponteiro
Usando B para acessar o valor = 42.000000
and the transformation
pD = (double*)A;
printf("Usando B para acessar o inicio de A[][] = %f\n", ***pB);
showcase
Usando B para acessar o inicio de A[][] = 42.420000
And it’s clear that pB
points to the beginning of A
. Only the index information is gone.
In addition to the base you need to have the offset. So you can only access the first --- without doing the math. And using the indexes will not be accepted by the compiler because it does not have this information.
Recovering the displacement
pA = (double(*)[3][3])pD;
printf("Usando B para acessar A[2][2] = %f\n", (*pA)[2][2]);
That’s the transformation that you spoke of. And it shows
Usando B para acessar A[2][2] = 84.840000
The expected value, after a cast to the correct format. But it only works if you know the size and so on.
The whole program
#include <stdio.h>
int main(void)
{
double A[3][3];
// agora uma "hierarquia"
double um_double = 42.;
double* pD = &um_double;
double** B = &pD;
// um ponteiro para A
double (*pA)[3][3] = &A;
// um ponteiro para B
double*** pB = &B;
A[0][0] = 42.42; // um exemplo
A[2][2] = 84.84;
// usando os ponteiros para acessar os dados
printf("A[0][0] = %f (usando o ponteiro\n", (*pA)[0][0]);
printf("Usando B para acessar o valor = %f\n", ***pB);
pD = (double*)A;
printf("Usando B para acessar o inicio de A[][] = %f\n", ***pB);
pA = (double(*)[3][3])pD;
printf("Usando B para acessar A[2][2] = %f\n", (*pA)[2][2]);
return 0;
};
The way out
A[0][0] = 42.420000 (usando o ponteiro
Usando B para acessar o valor = 42.000000
Usando B para acessar o inicio de A[][] = 42.420000
Usando B para acessar A[2][2] = 84.840000
Then I’ll have to resort to dynamic memory allocation to change the array declaration! Thanks.
– João Verçosa