I'm playing around pointers and arrays, and i want to cast/convert a pointer to an array of int (allocated with malloc) to a multidimensional array of int.
This is a very good idea. I’ve discovered this year that you can have pointer to arrays, and this is very useful when you want to parse a block of memory like a multidimensional array (because it comes from a struct in which the array dimensions can vary, for example). This post is very old, but let’s add an answer.
I have one more question: what's the difference between the following declarations?
int m1[10];
int (*m2)[10];
They are not the same at all!
m1 is an array of ten integers. It occupies 10 * sizeof(int) bytes, which is typically 40 bytes.
m2 is a pointer to such an array. So it is just a pointer. It can be assigned NULL, for instance. It just stores an address. It occupies sizeof(void *) bytes, typically 8 bytes nowadays.
When you have an array, you can change it directly to a pointer, and use the pointer the same way you use the array:
int m[10], * mPtr = m;
assert(m[i] == mPtr[i]);
This is actually just the same for multidimensional arrays, giving that a multidimensional array is an array of arrays:
int m[10][10], (* mPtr)[10] = m;
assert(m[i][j] == mPtr[i][j]);
So when you want a pointer, you have to omit the first dimension, because it is actually not needed to compute the address of a cell. &mPtr[i][j] is computed as mPtr + i * sizeof(int[10]) + j * sizeof(int) (which is also mPtr + i * sizeof(*mPtr) + j * sizeof(**mPtr). When you go onto the next i, it jumps ten ints as you expect.
Hence the solution to your problem:
str->val = malloc(sizeof(int[4][4]));
int (* m)[4] = (int (* )[4])str->val;
As a conclusion, C has actually good features/syntaxes to deal with multidimensional arrays, especially matrices. Only the declaration of the pointer is ugly, this is why I commonly use macros for it. See these test cases and the macro definitions. For your case, it could be used like that:
PtrDim2(int, m, 4, 4, str->val);
To declare and initialize m just like above. The first dimension is simply like a comment, actually you can omit it completely if you want: PtrDim2(int, m, , 4, str->val);.