Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic memory allocation code explanation

Being a beginner C/C++ programmer, I am having to spend several hours, trying to decipher the code below: Could someone walk me (step me through the code below for dynamic memory allocation) line by line.

 char **alloc_2d_char(const int rows, const int cols) 
 {
   char *data = (char *)malloc(rows*cols*sizeof(char));
   char **array= (char **)malloc(rows*sizeof(char*));

   for (int i=0; i<rows; i++)
      array[i] = &(data[cols*i]);

   return array;
 }

Pointer to Pointers is explained separately than from Pointers to Arrays. I have been able to get parts of the information from various sources, but none that stitches the lines cohesively.

like image 846
Ashmohan Avatar asked Jan 19 '23 11:01

Ashmohan


2 Answers

The code is using a single contiguous block of memory to hold a 2-D array.

char *data = (char *)malloc(rows*cols*sizeof(char));

Ok -- this line is allocating space for the entire 2-D array. The 2-D array is rows rows by cols columns. So the total number of elements is rows * cols. Then you have to multiply that by the amount of space each element takes up, which is sizeof(char) since this is a 2-D array of char. Thus the total amount of memory to be allocated is rows * cols * sizeof(char) which is indeed the argument to malloc.

The malloc call returns a pointer to the allocated memory. Since this memory will be used to hold char, you cast the return value to char *.

char **array= (char **)malloc(rows*sizeof(char*));

array is being declared as type "pointer to pointer to char" because that's what it's going to do. It'll point to memory that will hold pointers to char. It will be one pointer for each row. So you have to allocate rows * sizeof(char *) memory: the number of pointers times the size of a pointer of the right type. And since this was allocated to point to pointers to char, we cast the return value to char **.

for (int i=0; i<rows; i++)
   array[i] = &(data[cols*i]);

This is the magic :). This sets each pointer in array to point to within the block of actual data allocated earlier. Consider a concrete example where rows is 2 and cols is 3. Then you have the block of 6 characters in memory:

 [0][1][2][3][4][5]

And data[n] (for n from 0 to 5) is the n-th element and &data[n] is the *address of the n-th element.

So what that loop does in this case is do:

array[0] = &data[0];
array[1] = &data[3];

So array[0] points to the sub-block starting at [0] and array[1] points to the sub-block starting at [3]. Then when you add the second subscript you're indexing from the start of that pointer. So array[0][2] means "get the pointer stored in array[0]. Find what it points to, then move ahead 2 elements from there.:

array[0] points to [0][1][2] (well, actually points to [0]). Then you move two elements ahead and get [2].

Or if you start with array[1][1], array[1] points to [3][4][5] (and actually points at [3]. Move one element ahead and get [4].

like image 54
QuantumMechanic Avatar answered Jan 30 '23 23:01

QuantumMechanic


The first malloc is getting memory for the 2D character array. The second malloc is getting memory for rows index.

The for loop is setting the pointer to each row.

Finally the row index is returned.

like image 24
Richard Schneider Avatar answered Jan 30 '23 22:01

Richard Schneider