Here we are discussing pointers and 2D array. While we are discussing the 2D array, the representation of the 2D array is in matrix form. Example:

```
int arr[3][4] = {
{11,22,33},
{55,66,77},
{11,88,99}
};
```

The 2D array can be visualized in matrix form:

```
COL 0 COL 1 Col 2
ROW 0 11 22 33
ROW 1 55 66 77
ROW 2 11 88 99
```

We use terminology like rows and columns when talking about arrays. Because computer memory is linear and does not have rows and columns, this concept is just theoretical. So, how are 2-D arrays truly kept in memory? Arrays are stored in C in row-major order. This simply means that row 0 is saved first, followed by row 1, row 2, and so on.

The following representation shows a 2D array in memory:

```
0-th 1-st 2-nd
1D Array 1D Array 1D Array
==============|==============|=============
11 22 33 55 66 77 11 88 99
100 104 108 112 114 116 120 124 128
```

Here is the most important concept you need to remember in the multi-dimensional array:

A 2-D array is actually a 1-D array in which each element is itself a 1-D array. So arr is an array of 3 elements where each element is a 1-D array of 3 integers.

Important

In this case, of a **2D **array, the** 0th **element is a** 1D **array. As a result, the type or base type of arr in the above example is a pointer to an array of four integers. Because pointer arithmetic is done in terms of the pointer’s base size. If arr points to address **2000**, then **arr + 1** points to address** 2016** **(i.e. 2000 + 3*4)** in the case of arr.

We know that the array’s name is a constant pointer pointing to the array’s **0th** element. The **0th** element in a two-dimensional array is a one-dimensional array. In the case of a **2-D** array, the array name is a pointer to the **0th** **1-D** array. As a result, arr is a pointer to a four-element array in this situation. If the address of the 0th **1-D** is **2000**, then** (arr + 1) **represents the address **2012**, and **(arr + 2)** represents the address **2028**, according to pointer arithmetic.

From the above discussion, we can conclude that:

`arr`

points to 0th 1-D array.`(arr + 1)`

points to 1st 1-D array.`(arr + 2)`

points to the 2nd 1-D array.

```
arr => 11 22 33
arr + 1 => 55 66 77
arr + 2 => 11 88 99
```

We can write the following in general:

**(arr + i)** is the index of the ith **1-D** array.

Dereferencing a pointer to an array returns the array’s base address, as we discussed earlier in this chapter. Dereferencing arr yields **arr***, ***whose base type is (int)**. Similarly, when we decode **(arr+i)** we get ***(arr+i)**. In general, we can state the following:

The base address of the ith **1-D** array is pointed to by ***(arr+i)**.

It’s worth noting that while type **(arr + i)** and ***(arr+i)** both refer to the same address, their basic types are completely different. **(arr + i)** is a pointer to a three-int array, whereas ***(arr + i)** is a pointer to int or** (int*)**.

So, how can you access individual items in a 2-D array using arr?

We should be able to access elements of ith 1-D array using pointer arithmetic because ***(arr + i) points to the base address** of every ith 1-D array and is of base type pointer to int.

Let’s have a look at how we can accomplish this:

The address of the

0th element of the 1-D array is pointed to by ***(arr + i)**. As a result,** *(arr +i) + 1** denotes the address of the 1-D array’s first element. ***(arr + i) + 2 **is the address of the 1-D array’s second element.

As a result, we can deduce that:

***(arr + i) + j** points to the base address of the ith 1-D array’s **jth** element.

We may get the value of the jth element of the ith 1-D array by dereferencing ***(arr + i) + j**.

```
*( *(arr + i) + j)
```

We can obtain the value of the jth element of the ith **1-D** array using this expression.

Furthermore, the subscript notation is equal to the pointer notation ** *(*(arr + i )+ j**).

The following program shows how to use pointer notation to retrieve the values and addresses of elements in a **2-D **array.

#include<stdio.h> int main() { int arr[3][4] = { {11,22,33}, {55,66,77}, {11,88,99} }; int i, j; for(i = 0; i < 3; i++) { printf("Address of %d th array %u \n",i , *(arr + i)); for(j = 0; j < 4; j++) { printf("arr[%d][%d]=%d\n", i, j, *( *(arr + i) + j) ); } printf("\n\n"); } // signal to operating system program ran fine return 0; }

**Output:**

```
Address of 0 th array 2686736
arr[0][0]=11
arr[0][1]=22
arr[0][2]=33
Address of 1 th array 2686752
arr[1][0]=55
arr[1][1]=66
arr[1][2]=77
Address of 2 th array 2686768
arr[2][0]=11
arr[2][1]=88
arr[2][2]=99
```

## Assigning 2-D Array to a Pointer Variable

You can assign the array’s name to a pointer variable, however, unlike with a 1-D array, you’ll require a pointer to an array rather than a pointer to int or (int *). Here’s an illustration:

```
int arr[2][3] = {
{33, 44, 55},
{11, 99, 66}
};
```

Always keep in mind that a** 2-D **array is a** 1-D **array with each element being a **1-D** array. As a result, arr is a two-element array with each element being a one-dimensional arr of three integers. As a result, you’ll need a pointer to an array of** 3 **integers to store arr’s base address.

Similarly, if a **2-D **array includes three rows and four columns, such as int **arr[3][4]**, you’ll need a pointer to a **four-int** array.

`int (*p)[3];`

Here, p is a pointer to a three-int array. So, according to pointer arithmetic, p+i corresponds to the ith **1-D** array, whereas **p+0** corresponds to the **0th 1-D** array, **p+1** to the 1st **1-D** array, and so on. **(p+i) **has a pointer to a three-int array as its base type. We can access the base address of ith **1-D** array if we dereference **(p+i)**, but now the base type of ***(p + i)** is a pointer to int or **(int *)**. To get the address of the jth element of the ith **1-D** array, simply add j to ***(p +i)** as a result, ***(p +i) + j** denotes the address of the jth element of the ith **1-D** array.

The following program demonstrates how to access elements of a 2-D array using a pointer to an array.

#include<stdio.h> int main() { int arr[3][3] = { {11,22,33}, {55,66,77}, {11,88,99} }; int i, j; int (*p)[3]; p = arr; for(i = 0; i < 3; i++) { printf("Address of %d th array %u \n",i , p + i); for(j = 0; j < 4; j++) { printf("arr[%d][%d]=%d\n", i, j, *( *(p + i) + j) ); } printf("\n\n"); } // signal to operating system program ran fine return 0; }

**Expected Output:**

```
Address of 0 th array 2686736
arr[0][0]=11
arr[0][1]=22
arr[0][2]=33
Address of 1 th array 2686752
arr[1][0]=55
arr[1][1]=66
arr[1][2]=77
Address of 2 th array 2686768
arr[2][0]=11
arr[2][1]=88
arr[2][2]=99
```