You create a 2-dimensional array using the knowledge you already have about creating a 1-dimensional array. As you've started doing, you create a 1D array of 1D arrays.
First you make a variable to hole the array of arrays: done.
Next you create the array to hold the other arrays and assign that to the variable: done.
Next you create all those other arrays and assign them to the positions in the array: NOT done.
It helps a lot if you typedef the kind of pointer that goes in the first array.
So you're just missing the loop that creates all those actual data arrays. You already have the array to hold them all. Think you can finish it now?
btw this kind of array even allows for the secondary arrays to be of differing lengths.
Now the other way to create a 2-D array of m*n items is to simply create an array that is m*n big. Then you step across in multiples of m to go down by one n. That's how bitmaps do it too. This method is usually preferred because it is more efficient. However, unlike the other method, this way you can't use the array[m][n] syntax. Instead it's better to make a function to to the lookups, and then you get the even better syntax of: lookup(m, n).