Reputation: 1321
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.
I don't know why the following C program doesn't print the same number two times.
...
str->val = malloc(16);
int (*m)[4][4] = str->val;
printf("The number is %d, yes the number is %d", str->val[4+1], (*m)[1][1]);
...
Now, the first printed number is right, but the second one is not. I found other question on SO similar to mine, but i couldn't resolve my problem. I'm sorry for the possible duplication.
I have one more question: what's the difference between the following declarations?
int m[10];
int (*m)[10];
EDIT:
My problem is caused by a wrong declaration of the field val of my struct: I declared it as char.
Upvotes: 0
Views: 76
Reputation: 290
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);
.
Upvotes: 0
Reputation: 3997
Using the nice cdecl.org tool, int (*m)[4][4]
is translated to declare m as pointer to array 4 of array 4 of int
, which is multidimensional array. It should work if you allocated more memory.
int m[10];
is array of 10 integers stacked as a row in memory.
int (*m)[10];
is a pointer to an array which holds 10 values.
int m[4][5]
is multidimensional array, but they are almost like int m[20]
. They are stacked as a row in memory. Indexing m[2][0]
is simply translated to m[5*2 + 0]
.
int *m[5]
is NOT multidimensional array, it is array of pointers. Each pointer points to a different array. Values are not stored in sequence.
Upvotes: 2
Reputation:
Your problem is that 16 bytes ain't enough for your array. Common values of sizeof(int)
are 2 and 4, so you need at least 32 or 64 bytes for representing 4 int
s. But you shouldn't be sticking hard-wired constants into your code anyway. Use the sizeof
operator, and it will work:
int (*arr)[4][4] = malloc(sizeof(*arr));
int *ptr = &(*arr)[0][0];
// fill it with something, then:
printf("%d = %d\n", (*arr)[1][1], ptr[1 * 4 + 1]);
Upvotes: 1