Multidimensional arrays allocated through calloc

I have a question about how memory is allocated when I calloc . I examined this question, but does not consider how memory is allocated in the case of a dynamically distributed two-dimensional array.

I was interested to know if there is a difference in memory representation between the three ways to dynamically allocate a two-dimensional array.

Type 1:

 double **array1; int ii; array1 = calloc(10, sizeof(double *)); for(ii = 0; ii < 10; ii++) { array1[ii] = calloc(10, sizeof(double)); } // Then access array elements like array1[ii][jj] 

Type 2:

 double **array1; int ii; array1 = calloc(10 * 10, sizeof(double *)); // Then access array elements like array1[ii + 10*jj] 

Type 3:

 double **array1; int ii; array1 = malloc(10 * 10, sizeof(double *)); // Then access array elements like array1[ii + 10*jj] 

From what I understand in calloc and malloc , the difference between the last two is that calloc will zero out all elements of the array, while malloc will not. But are the first two ways to determine the equivalent array in memory?

+10
c malloc calloc
source share
4 answers

Are the first two ways to determine the equivalent array in memory?

Not really. In the second type, they are almost certainly adjacent, while in the first type this is not necessary.

Type 1: in memory will look like this:

  +---+---+---+---+---+---+---+---+---+---+ double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +---+---+---+---+---+---+---+---+---+---+ ^ |------------------------------------ . . . . . . . . | // ten rows of doubles - +---+---+---+---+---+---+---+---+---+--|+ double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0|| +---+---+---+---+---+---+---+---+---+--|+ ^ . . . - | ^ ^ ^ . . . . . | | | | | ^ ^ ^ ^ ^ | +-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+ array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | // each cell points to ten doubles +---+---+---+---+---+---+---+---+---+---+ ^ | | +-|-+ array1| | | +---+ 

Type 2: in memory will look like this:

  +---+---+---+---+---+---+---+---+---+---+ +---+ double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | +---+---+---+---+---+---+---+---+---+---+ +---+ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | | | | | | | | | | | | | | +-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+ +-|-+ array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... |99 | // each cell points to one double +---+---+---+---+---+---+---+---+---+---+ +---+ ^ | | +-|-+ array1| | | +---+ 
+7
source share

Simple example

 #include<stdio.h> #include<stdlib.h> int **d ; int sum(); //---------------------------------------------- int main(){ d = (int **)calloc(3,sizeof(int*)); printf("\n%d",sum()); } //----------------------------------------------- int sum(){ int s = 0; for(int i = 0; i < 3; i++) d[i] = (int *) calloc (3,sizeof(int)); for(int i = 0; i < 3; i++){ for(int j = 0; j < 3; j++){ d[i][j] = i+j; s += d[i][j]; printf("\n array[%d][%d]-> %d",i,j,d[i][j]); } } return s; } 
+1
source share

In the first case, you select 10 pointers to double, and 100 doubles. In the second case, you allocate 100 pointers to double. Another difference is that in the second case, you allocate one large block of memory, so that all the elements of your array are in one block. In the first case, each "row" of your array is in a different block than the rest. Although, secondly, your array should be double *, not double **, because in this case of allocation, your array contains only pointers to double, not double.

-one
source share

In case 1 you do:

 array1[0] -> [memory area of 10] array1[1] -> [memory area of 10] ... array1[N] -> [memory area of 10] ... 

Note. You cannot assume that the memory area is continuous, there may be spaces.

In case 2 you do:

 array1 -> [memory area of 100] 

Case 3 is similar to case 2, but does not initialize the memory. The difference between cases 1 and 2 and 3 is that in the first case, you really have a 2D memory structure. For example, if you want to swap lines 1 and 2, you can simply swap pointers:

 help = array1[1] array1[1] = array1[2] array1[2] = help 

But if you want to do the same in case of 2 & 3, you need to make real memcpy. What to use? Depends on what you do.

The first method uses a memory bit: if you had a 1000x10 array, then the first version will use 1000 * 8 + 1000 * 10 * 8 (on a 64-bit system), while 2 and 3 will only use 1000 * 10 * 8.

-one
source share

All Articles