All right... what you have here, basically, is a pointer-pointer, namely, the adress of an adress. You can use this kind of variable when dealing with arrays.
The first two lines of your code are equivalent to :
int* a[5]; // Declaration of an array of 5 integer pointers (a[0] till a[4]).
A "pure" C code doesn't use variable for the size of an array, so you use the malloc when you want to edit dynamically the size of the array.
Meaning, if in your code, you are not going to change the size of your arrays, you are using a very complex way to achieve a very simple goal. You could just type :
int a[5][3];
But if you do not know the size of your array, you have to use the mallocs (and then, free). What you are doing, basically, is :
- Declaring an array of array;
- Allocating the memory for x number of POINTER to integer arrays;
- For each of these POINTERS, allocating memory for y integers.
Now that you have done this, you can use your arrays normally. For instance :
a[1][0] = 1;
will mean : in the first array [1], the first row [0] is 1.
The only difference with a standard declaration like the one above, without the mallocs, is that since you allocated memory, you'll have to free it. Which is why you don't want to lose your variable a**. At the end of your function, the pointer-to-pointer variable will be destroyed, but not the memory you allocated.