1

I am somewhat new to C programming. I have a doubt regarding dynamic memory allocation. The following is a code in the main program for memory allocation.

double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);

I want to call the function and create elements in the matrix inside the function. Do I have once again allocation memory inside the function like below or Is there any other method to avoid this tedious memory allocation repetition. Following is the function.

`double** create_square_matrix(int n)
{
int i,j,sum=0;
double **array2=(double**)malloc(sizeof(double*)*n);
array2[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
array2[i] = array2[i-1] + n;
for (i = 0; i < n; ++i)
  {
      for (j = 0; j < n; ++j)
      {
        sum=sum+j;
        array2[i][j]=sum;
      }
  }
return array2;
}

` The above function returns the array which is stored in the 'mat' variable. And another question is how do I free the memory of variable 'array2' inside the function after using the return method. I can't free the memory possibly before returning the array. Is there a method to free the memory in the above function.

Vickky
  • 11
  • 2
  • 1
    Please read [this](http://stackoverflow.com/questions/20094394/why-do-we-cast-return-value-of-malloc/20094422#20094422) why casting for `malloc` is not required – Ed Heal Apr 30 '16 at 09:10

3 Answers3

1

Your function create_square_matrix allocates memory and then fills it by some values.

Your top piece of code allocates memory, and then calls create_square_matrix which again allocates memory. It is like to mop floors before calling the janitor who also mops floors. You don't need to allocate memory twice. Not only it is unneccessary, in fact it is bad. Since you perform two allocations, the memory from the first one is lost, and there is no way to free it. This is called memory leak. Instead of

double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);

you should write

double **mat = create_square_matrix(n);
user31264
  • 6,557
  • 3
  • 26
  • 40
0

As mentioned, in C there's no need to cast to/from void*. Also, your calloc is backwards: use N elements for the first argument, sizeof(element) for the second.

I will answer your question, and then suggest a better approach.

You are choosing double ** for your matrix. Even if it weren't square, you know exactly how many pointers and how many doubles you need, and of course how big each type is. So,

double **M = malloc( n * sizeof(double*) + n * m * sizeof(double) );

does the trick, does it not? If sizeof(double*) == sizeof(double) for your machine (probably true), then

double **M = calloc( (1+n) * m, sizeof(double) );

works, too, but less portably. You also get the zeros for free; you'll have trouble finding a machine for which it's not true that double f=0 yields a value for which all bits are zero.

But why define your matrix as an array of pointers? Why not instead define it as an array of doubles?

double *M = calloc( n * m, sizeof(double) );

Better yet, for the past 15 years or so, C has supported variable-length arrays, meaning you can define arrays whose size is determined at runtime. Back in K&R days, you could define an array M[n] unless n was a static constant or enum. If your arrays aren't ginormous -- meaning that for the machine in question they'll fit comfortably on the stack -- you can skip malloc and simply define your matrix by a size determined at runtime.

Even if you can't do that, can typedef one dimension dynamically,

typedef double (x_axis_t)[m];
double x_axis_t *M = calloc( n * sizeof(x_axis_t), sizeof(double) );

which is nice, because then you can access your array as

M[x][y];

Just don't try to use M[x,y], because that's something else altogether.

BTW, since you're new to the game, to use a c99 compiler, the standard command is c99, not cc. See your friendly manual for details. :-)

James K. Lowden
  • 7,574
  • 1
  • 16
  • 31
-1

Using a nice function macro for memory allocation is always a good idea. Unless you have to free memory manually I would leave it to a garbage collector such as libgc. Below is an example. If you don't want to use a garbage collector you can just replace GC_MALLOC with malloc. When you free the array (manually) you must first free the individual rows.

#include <gc/gc.h>
#include <stdio.h>
#include <stdlib.h>

#define NEW_ARRAY(ptr, n) (ptr) = GC_MALLOC((n) * sizeof (ptr)[0])

double **SquareMatrix(int n)
{
    double **A;
    int i, j;

    NEW_ARRAY(A, n);
    for (i = 0; i < n; i++) {
        NEW_ARRAY(A[i], n);
        for (j = 0; j < n; j++) {
            A[i][j] = 0.0;
        }
    }
    return A;
}


int main(void)
{
    const int n = 5;
    double **A;
    int i, j;

    A = SquareMatrix(n);    
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("%5.2f ", A[i][j]);
        }
        putchar('\n');
    }

    return 0;
}
August Karlstrom
  • 10,773
  • 7
  • 38
  • 60