0

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.

2
  • 1
    might find this useful unixwiz.net/techtips/reading-cdecl.html Commented Jan 19, 2014 at 23:08
  • 1
    malloc(16) will only allocate enough memory for an int array[0][4]. Commented Jan 19, 2014 at 23:29

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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 ints. 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]);

Comments

0

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);.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.