Wednesday, June 11, 2008

2D Arrays in C Using malloc

Pointers can be easily used to create a 2D array in C using malloc. The idea is to first create a one dimensional array of pointers, and then, for each array entry, create another one dimensional array. Here's a sample code:
double** theArray;
theArray = (double**) malloc(arraySizeX*sizeof(double*));
for (int i = 0; i < arraySizeX; i++)
theArray[i] = (double*) malloc(arraySizeY*sizeof(double));
Voila!

What I usually do is create a function called Make2DDoubleArray that returns a (double**) and then use it in my code to declare 2D arrays here and there

double** Make2DDoubleArray(int arraySizeX, int arraySizeY) {
double** theArray;
theArray = (double**) malloc(arraySizeX*sizeof(double*));
for (int i = 0; i < arraySizeX; i++)
theArray[i] = (double*) malloc(arraySizeY*sizeof(double));
return theArray;
}
Then, inside the code, i would use something like
double** myArray = Make2DDoubleArray(nx, ny);
Voila!

Of course, do not forget to remove your arrays from memory once you're done using them. To do this

for (i = 0; i < nx; i++){
free(myArray[i]);
}
free(myArray);


UPDATE: JULY 10, 2008
As was noted by an anonymous comment, a great advantage of declaring a 2D array in this manner is the ability to use it as myArray[i][j], a very intuitive form.

Cite as:
Saad, T. "2D Arrays in C Using malloc". Weblog entry from Please Make A Note. http://pleasemakeanote.blogspot.com/2008/06/2d-arrays-in-c-using-malloc.html

25 comments:

  1. Hello.

    Thanks for the short but very useful code snippets you present here. But I think there is a little mistake: In line 2 of the first snippet and also in line 3 of the second one, it should be
    "theArray = malloc(arraySizeX*sizeof(double*));",
    i.e. without the "(double*)" in front of malloc.
    Also you could mention that the pro about this way of building up 2D arrays using malloc is that you can use the usual "myArray[i][j]" command in the main function.

    Thanks again for this great entry and especially the second code snippet defining the function.

    ReplyDelete
  2. Thanks for your comment.

    The (double*) is needed in front of the malloc because malloc is defined as a (void*) pointer, and thus you will need to cast it as (double*) or any other datatype for that matter.

    I agree with your comment on the use of the 2D array (i.e. myArray[i][j]). It is now added to the post.

    ReplyDelete
  3. UPDATE: There was a typo in the first code snippet, and now it is corrected.

    ReplyDelete
    Replies
    1. Thanks very much for this. Actually the entire blog is so helpful!!

      Delete
  4. thanks .. been really helpful :)

    ReplyDelete
  5. Thank you so much!
    Very helpful :D

    ReplyDelete
  6. Thanks very helpfull :)

    ReplyDelete
  7. I think, there is no need of explicit casting in line 4 and also in line 2. It will automatically converted into (double**) and (double*) in line 2 and line 4 respectively by implicit type conversion.
    please see.....
    http://c-faq.com/malloc/cast.html
    and
    http://c-faq.com/malloc/mallocnocast.html

    ReplyDelete
  8. please read the section "Don't cast the value returned by malloc or calloc:" of link... http://prokutfaq.byethost15.com/DynamicMemoryAllocation
    It is quite informative.

    ReplyDelete
  9. Sorry to add this to a very old thread, but I believed that, to make such code compatible with C++ compilers (should you have to compile C code on a C++ compiler), a casting of the initially void pointer returned by malloc was indeed required.

    ReplyDelete
  10. What is this: double** Make2DDoubleArray(int arraySizeX, int arraySizeY) {
    double** theArray;
    theArray = (double**) malloc(arraySizeX*sizeof(double*));
    for (int i = 0; i < arraySizeX; i++)
    theArray[i] = (double*) malloc(arraySizeY*sizeof(double));
    return theArray;
    }

    I just can't get it!

    ReplyDelete
  11. Thanks very useful, I wonder why this language can work properly with some java applications, thanks.

    ReplyDelete
  12. but be careful because it does not result an array like the one we have when we declare it.
    When we declare an array the array makes sense as a whole. Even if the name of array is a pointer that its VALUE is the address of the first element of the array but is a pointer about the array as a whole not a pointer to the first element.
    In this article's code Make2DDoubleArray does not return a pointer to 2D array but a pointer to a pointer. It isn't the same.
    For this reason in this situation the value of theArray is not equal to theArray[0] as we have when an array declares normal (without malloc())

    ReplyDelete
  13. This technique leads to memory fragmentation and is useless for caching. Better to allocate all dimensions in one malloc() if possible.

    ReplyDelete
    Replies
    1. Or, better:

      int (*table)[columns] = malloc(rows * sizeof *table);

      Delete
  14. Thanks!!! Good Job... But could you tell me something? How do you fill with random numbers a 2D array after creating it?
    i only know how to do it with 1D array

    ReplyDelete
    Replies
    1. If i may say so:


      srand(time(NULL));

      for(i=0; i< X; i++)
      {
      for(j=0; j< Y; j++)
      {
      array2d[i][j] = rand%MAXVAL;
      }
      }

      Delete
  15. Great use with this..!
    But tell me why we use the casting as (double**)
    please make note about use of casting..
    thank you .

    ReplyDelete
  16. 1st hit on Google, best way to refresh my knowledge!
    Thumbs up, sir.

    ReplyDelete
  17. Casting the return value of malloc in C is just wrong. You are using a C++ compiler if you are getting an error because, in C++, there exists no implicit conversion from void* to whatever*. That is not true in C, and casting the result can actually hide an error in your code. The cast will, in older compilers, suppress n error if you forgot to include . In C you do not make the cast, period.

    ReplyDelete