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.
The code is using a single contiguous block of memory to hold a 2-D array.
Ok — this line is allocating space for the entire 2-D array. The 2-D array is
rowsrows bycolscolumns. So the total number of elements isrows * cols. Then you have to multiply that by the amount of space each element takes up, which issizeof(char)since this is a 2-D array ofchar. Thus the total amount of memory to be allocated isrows * cols * sizeof(char)which is indeed the argument tomalloc.The
malloccall returns a pointer to the allocated memory. Since this memory will be used to holdchar, you cast the return value tochar *.arrayis 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 allocaterows * 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 tochar **.This is the magic :). This sets each pointer in
arrayto point to within the block of actual data allocated earlier. Consider a concrete example whererowsis 2 andcolsis 3. Then you have the block of 6 characters in memory:And
data[n](fornfrom0to5) 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:
So
array[0]points to the sub-block starting at[0]andarray[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. Soarray[0][2]means “get the pointer stored inarray[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].