Matthew Schell
Matthew Schell

Reputation: 679

How to create a pointer to a multi dimensional array in C

Before anyone closes this question because there's another related one, hear me out. I've already looked at the other question and I didn't get it. I would like to create a pointer to a multi dimensional array but I don't know how. I thought I was supposed to do it like this:

int test_arr[2][4];
int *ptr_array = test_arr;

But when I do that, I get a warning saying:

incompatible pointer types initializing 'int *' with an expression of type 'int [2][4]'

I have no idea what I'm doing wrong. Can someone help me please?

Upvotes: 1

Views: 1199

Answers (2)

H.S.
H.S.

Reputation: 12669

You need to understand the basics.
[Below in post, read 1D as 1 dimension and 2D as 2 dimension]

First, lets take an example of pointer to 1D array:

Take an int type and a pointer pointing to it:

int x = 1;
int *px = &x;

The type of x is int and the type of &x is int * and type of px is int * i.e. it can hold the address of an int type variable. Hence the assignment is valid.

Take a 1D int array and a pointer pointing to it:

int arr[2] = {1,2};
int *parr = arr;

Note that the type of px and parr is same i.e. int * and assigning arr to parr is completely valid although the arr is a 1D array. This is because of the fact that, in C, an array of type converted to pointer of type that points to the initial element of the array object but there are few exceptions to this rule and one of them is when used unary & operator.
The type of arr is int [2] but in the above statment (parr declare and initialisation statement) it is converted to pointer pointing to initial element of array which is an integer i.e. arr is converted to int * type in the int *parr = arr; statement. Hence, it is valid to assign arr to parr or to any variable of type int *.

As, I have mentioned that there are few exceptions to the rule (array of type converted to pointer of type....) and one of the exception is when used unary & operator. So type of &arr will be int (*)[2]. That means you can assign &arr to any variable of type int (*)[2].

int (*parr2)[2] = &arr;

i.e. parr2 is a pointer to an array of 2 integer.

The difference between this

int *parr = arr;

and

int (*parr2)[2] = &arr;

is that parr can hold address of any int pointer but parr2 can hold the address of any array of 2 integers. Both are pointing to same address but their types are different.

If you understood the above mentioned things completely then read below otherwise read the above part again.

Now lets come to 2D array.

Take a 2D array and a pointer pointing to it:

int arr[2][2];
int (*ptr)[2] = arr;

In the above ptr declare and initialisation statement, the type of arr is int (*)[2]. Why??
Recall the rule mentioned above - array of type converted to pointer of type that points to the initial element of the array object.
arr is array of 2 1D arrays of size 2 (2 int elements). So, it's first element is array of 2 int and, by rule, it will be converted to pointer to the initial element i.e. pointer to 1D array of 2 int which is int (*)[2].
Hence, you can assign arr to a pointer variable of type int (*)[2].

The type of &arr is int (*)[2][2], so this is also perfectly fine:

int (*ptr2)[2][2] = &arr;

So, there are two ways you can have pointer to 2D arr but remember that the types of ptr and ptr2 is different. This matters, for e.g., if you add 1 to pointer ptr it will be incremented by size of int [2] but if you add 1 to ptr2 it will be incremented by size of int [2][2].

How to access the array members using pointer:

In case of 1D array:

int arr[2] = {1,2};
int *parr = arr;
int (*parr2)[2] = &arr;

// access arr members via parr pointer
printf ("%d\n", parr[0]);  // this will give value of first member of array arr

// access arr members via parr2 pointer
printf ("%d\n", (*parr2)[0]);  // this will give value of first member of array arr

Similarly, in case of 2D array:

int test_arr[2][4];
int (*ptr_array)[4] = test_arr;
int (*ptr_array2)[2][4] = &test_arr;

// access test_arr members via ptr_array pointer
printf ("%d\n", ptr_array[0][0]); // this will give value of first member of array test_arr

// access test_arr members via ptr_array2 pointer
printf ("%d\n", (*ptr_array2)[0][0]); // this will give value of first member of array test_arr

Based on above explanation, try yourself creating multidimensional array (> 2D array) pointers and play with them.

Hope, above explanation resolves your all confusions related to pointer to a 2D array and you understood now why compiler is giving incompatible pointer types .... warning on statement int *ptr_array = test_arr;. It's all about type compatibility during initialisation/assignment.

Upvotes: 1

vmp
vmp

Reputation: 2420

In order to do pointer arithmetic the pointer has to know the size of what it is pointing to.

int test_arr[2][4]; is equivalent to 2 elements of type int[4]. So whenever you add 1 to the pointer, it will jump the size of 4 integers. If you had int* it would increment the size of a single integer only.

Like said in the comments, what you want is: int (*ptr_array)[4] = test_arr;

I know, the syntax is a little weird, but that's how you do it.

Upvotes: 2

Related Questions