Pointers and Arrays


August 23, 2021, Learn eTutorial
1562

In this tutorial, you will learn the way to manipulate arrays using pointers, i.e how to access elements from an array using pointers, and how to traverse through arrays, etc with the help of some simple examples.

To understand the connection between arrays and pointers, it is always better to know the basics of C pointers and C Arrays beforehand. 

Pointers and One -Dimensional Array

Let’s start by examining a simple example that shows how to print the address of each array element in a one-dimensional array. 


#include<stdio.h>

int main() {
    int arr[5] = {
        10,
        20,
        30,
        40,
        50
    };
    for (int i = 0; i < 5; i++) {
        printf("The address of element %d in position arr[%d]: %d\n", arr[i], i, & arr[i]);
    }
    return 0;
}
 

Output:


The address of element 10 in position arr[0]: 6422016
The address of element 20 in position arr[1]: 6422020
The address of element 30 in position arr[2]: 6422024
The address of element 40 in position arr[3]: 6422028
The address of element 50 in position arr[4]: 6422032

In this example, we have declared an array with 5 elements: 10, 20, 30, 40, and 50. On declaration, the compiler allocates a sufficient amount of memory to store the elements of the array. Here, each element is stored continuously in the memory with a 4 bytes difference between consecutive elements which indicates the byte size of integer. See the below visualization of array elements in memory.

Array Pointer

When you observe the image carefully, you could get the answer to the question “ Is the address of array arr and arr[0] the same?”.  The answer is Yes because array arr always points to the first element which is arr[0], so the name of the array is the const pointer that points to the address of the first element. More precisely, 

Array Pointer

Pointers  to access the address of the array 

Normally to get the address of array elements we make use of the ampersand (&) symbol. We can also use pointers (*) to get the address of array elements. Let's see how we can modify the above program to get the address of array elements using pointers and produce the same outcome.


#include<stdio.h>

int main() {
    int arr[5] = {
        10,
        20,
        30,
        40,
        50
    };
    int * p;

    p = & arr[0];
    for (int i = 0; i < 5; i++) {
        printf("The address of element %d in position arr[%d]: %d\n", * p, i, p);
        p++;
    }
    return 0;
}
 

Output:


The address of element 10 in position arr[0]: 6422016
The address of element 20 in position arr[1]: 6422020
The address of element 30 in position arr[2]: 6422024
The address of element 40 in position arr[3]: 6422028
The address of element 50 in position arr[4]: 6422032

As we know that every element of a pointer has a specific address. Here we have used pointers and increment its address value gradually ( using for loop) to store them. In our example, we have an array arr[5] and a pointer p. We can use them like:
p=&arr[0];
p+1=&arr[1];
p+2=&arr[2];
p+3=&arr[3];
p+4=&arr[4];
p+5=&arr[5];
Similarly, we can use the value stored in it by printing the value of '*p', '*(*p+1)' .*(*p+2) etc.
While using pointers with an array, we need to bear in mind the following points:

  1. The data type of both array and pointer must be the same. 
  2. Arrayname can be used to initialize the pointer since arrayname is pointed to the address of the first element of the array.

Pointer Arithmetic (Increment and Decrement)

Pointers support arithmetic operations, but only addition(increment) and subtraction(decrement). In the case of integers when we increment a number by a unit, the value of the stored variable increases like 

4+1=5.

But in the case of pointers, incrementing implies letting the pointer point to the next address location. That is the address value of the cell changes instead of the stored variable's value as shown in the diagram below.

Array Pointer

An integer data type needs 4 bytes of memory, so an increment of pointers in these cases will eventually move the pointer by four units. Similarly, float pointers will increase the address value by 4 units, as each of them needs 4 bytes of space for allocation. 
When it comes to decrement the pointer will decrease the address value by the bytes of its corresponding datatype. Pointer immediately points to the previous address location. 

Since the pointer works on addresses the chance for multiplication and division is completely out of scope. 

Pointers to an  Array

So far we have discussed pointers that point to single elements of an array. But when a pointer points to a whole array, it is a different concept. In C, the pointer that refers to a whole array is known as a pointer to an array. See below the declaration of a pointer to an array.


datatype (*p)[n]
 

where data type represents the type of array,

  • p is the pointer points to the whole array.
  • n is the number of elements in the array.

Example:


int (*p)[5]
float (*p)[10]
 

The key point to be considered is that the round bracket or parentheses around ‘p’ is essential because int *p[5] and int (*p)[5] are different. int *p[5] denotes an array with 5 integer pointers while int (*p)[5] denotes a pointer to an array with 5 integers.


#include<stdio.h>

int main() {
    int arr[5];
    int * p;
    int( * pa)[5];

    p = arr;
    pa = arr;

    printf("Address of p = %d\n", p);
    printf("Address of pa = %d\n", pa);

    p++;
    pa++;

    printf("\n...After incrementing p and pa...\n\n");
    printf("Address of p = %d\n", p);
    printf("Address of pa = %d\n", pa);

    return 0;
}
 

Output:


Address of p = 6422000
Address of pa = 6422000

...After incrementing p and pa...

Address of p = 6422004
Address of pa = 6422020

Working Concept

When you examine the example you can see that p is a pointer that points to the first element of the array arr and hence its base type is a pointer to int. On the other hand, pa is a pointer that refers to the whole array arr and so its base type is a pointer to an array containing 5  integer elements.  When the two pointers increments, they work relative to the base type, and consequently the p is incremented by 4 bytes and pa incremented by 20 bytes( 5 x 4 = 20).

Pointers and Two -Dimensional Array

So far we have seen the working of pointers on one-dimensional arrays. Now let’s observe how pointers work on a Two - dimensional array. To get a better understanding of two-dimensional arrays refers to our previous tutorial ARRAYS.

Array Pointer

We know that a two-dimensional array can be simply visualized as a matrix with rows and columns.  But when it comes to the case of memory, a two-dimensional array can be considered as a one-dimensional array with each element itself is a one-dimensional array. This is because in memory everything is stored in a linear manner. The above diagram demonstrates the conceptual view of a two-dimensional array with 2 rows and 3 columns while the below one shows the actual view of a two-dimensional array with 3 rows and 3 columns in the memory. 

Array Pointer

From the diagram its is clear that in two dimensional array ,

arr[0] == arr : is the zeroth 1 -Dimensional array arr[1] == arr + 1 : is the first 1- Dimensional array

arr[2] == arr +2 : is the second 1- Dimensional array and so on. In general ,

arr[i] == arr + i : represents the ith 1-Dimensional array and so on. 

In general ,

arr[i] == arr + i  : represents the ith 1-D array . 

How to access the address of a 2-D Array using pointers

The following example shows how to print the address of each element in a two-dimensional array.
 


#include<stdio.h>

int main() {
    int arr[3][3]={10,20,30,40,50,60,70,80,90};
    int * p;

    p = arr;
    for (int i = 0; i < 3; i++) {
        printf("\n\nThe address of arr[%d]: %d\n", i, p);
        for (int j = 0; j < 3; j++) {
            printf("The address of element %d in position arr[%d][%d]: %d\n", * p, i, j, p);
            p++;
        }
    }
    return 0;
}
 

Output:


The address of arr[0]: 6421984
The address of element 10 in position arr[0][0]: 6421984
The address of element 20 in position arr[0][1]: 6421988
The address of element 30 in position arr[0][2]: 6421992


The address of arr[1]: 6421996
The address of element 40 in position arr[1][0]: 6421996
The address of element 50 in position arr[1][1]: 6422000
The address of element 60 in position arr[1][2]: 6422004


The address of arr[2]: 6422008
The address of element 70 in position arr[2][0]: 6422008
The address of element 80 in position arr[2][1]: 6422012
The address of element 90 in position arr[2][2]: 6422016

In this example to get the address of each element in the two-dimensional array, we use the pointer variable p. So behind the screen how pointer variable p actually works is as follows.

Let our array be arr and (arr + i) denote the ith 1-D array. To get the address we can prefix the dereference operator (*) directly with (arr+i).i.e,

 *(arr+i) gives the address of i th 1-D Array. 

More concisely,
*(arr + 0) ⇒ the address of 0th 1 - D Array
*(arr + 1) ⇒ the address of 1st 1 - D Array
*(arr + 2) ⇒ the address of 2nd 1 - D Array

Now to access  the address of elements in each array, we need to perform pointer arithmetic as follows

*(arr + 0)+0 ⇒ the address of 0th element of 0th 1 - D Array
*(arr + 0)+1 ⇒ the address of 1st element of 0th 1 - D Array
*(arr + 0)+2 ⇒ the address of 2nd element of 0th 1 - D Array
*(arr + 1)+0 ⇒ the address of  0th element of 1st 1 - D Array
*(arr + 1)+1⇒ the address of 1st element of 1st 1 - D Array
*(arr + 1)+2 ⇒ the address of  2nd element of 1st 1 - D Array

This can be generalized as 

*(arr + i)+j⇒ the address of jth element of ith 1 - D Array

It is also possible to access the values of each element in the array. This can be achieved by dereferencing *(arr + i)+j . i.e

*(*(arr + i)+j)⇒ the value of jth element of ith 1 - D Array

The above program can be changed as follows. 


#include<stdio.h>

int main() {
    int arr[3][3]={10,20,30,40,50,60,70,80,90};

    for (int i = 0; i < 3; i++) {
        printf("\n\nThe address of arr[%d]: %d\n", i, *(arr + i));
        for (int j = 0; j < 3; j++) {
            printf("The address of element %d in position arr[%d][%d]: %d\n", *( * (arr + i) + j), i, j, *(arr + i) + j);

        }
    }
    return 0;
}
 

Here instead of using pointer variables, we used the pointer on the array itself to access both address and values.