Reputation: 411
Usually people dynamically allocates matrices as
double **A;
int N,i,j;
N=10;
A = (double **)malloc(N*sizeof(double *));
for(i=0; i<N; i++)
{
A[i]= (double *)malloc(N*sizeof(double ));
}
Based on some discussion in the class, I have learned that this is not very efficient for large matrices. This creates an array of pointers to array allocated in different places in the memory, changing rows in this kind of allocation is more costly. So the instructor proposed using this form of allocation:
double *A;
int N;
N=10;
A = (double *)malloc(N*N*sizeof(double));
Where you access i,j element of the matrix by looking at A[N*i + j]. I would like to allocate my matrices like this but I would like to keep my old notation which is A[i][j]. Thus one way that comes to my mind is to do the bad allocation first, that is create double** A as described in the first part. Then set
A = (double **)malloc(N*sizeof(double *));
temp = (double *)malloc(N*N*sizeof(double ));
for(i=0; i<N; i++)
{
A[i]=&temp1[i*N+j];
}
This code seems to work but I know only the basics of memory allocation, so I would like to ask if there is anything problematic with this kind of allocation, is it any different than just keeping with the array temp1. Thanks
Upvotes: 2
Views: 134
Reputation: 40604
This is easy to do, just declare A
to be a pointer to a line array:
double (*A)[N] = malloc(N*sizeof(*A));
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
A[i][j] = /*whatever*/;
}
}
If the notation I used is unclear to you, read it from the inside out: A
is defined to be a pointer ((*A)
) to an array of N
elements ((*A)[N]
), which happen to be of type double
(double (*A)[N]
). This pointer is initialized with the return value of malloc()
(it might be irritating that the =
does not follow the identifier A
, but this is the same syntax as in char myName[] = "Foo, Bar B.";
). It might be a bit more clear if you split the line and/or use a typedef
:
double (*A)[N];
A = malloc(N*sizeof(*A));
or
typedef double MatrixLine[N];
MatrixLine* A = malloc(N*sizeof(*A));
In C (not in C++) the typedef
works fine even if N
is a dynamically computed value, I could even use typedef double MatrixLine[random()];
, not that it would make much sense... C is extremely flexible in this respect!
It might also be interesting to know how to cast a pointer to the type of A, here is the correct cast included:
double (*A)[N];
A = (double (*)[N])malloc(N*sizeof(*A));
Note that the cast is precisely the same syntax as the declaration of A
, only with the identifier omitted.
Note 1:
Since C99 you are allowed to declare loop variables right in the for()
statement. Use this, it makes your code much more readable.
Note 2:
In C, it is not required to cast the return value of malloc()
, and it does not add to your code to write it anyway. However, C++ does require the cast, so if you want to use your code in a C++ project, go ahead and cast.
Upvotes: 2