Pointer Arithmetic in C

You should know by now that a pointer is nothing more that a variable used to store a memory address. And if this is new to you go back and read Pointer Basics before continuing with this chapter. In this chapter, we will discuss arithmetic operations that can be performed on pointers.

We can't perform every type of arithmetic operations with pointers. Pointer arithmetic is slightly different from arithmetic we normally use in our day to day life. The only valid arithmetic operations applicable on pointers are:

  1. Addition of integer to a pointer
  2. Subtraction of integer to a pointer
  3. Subtracting one pointer from another of the same type

The pointer arithmetic is performed relative to the base type of the pointer. For example: if we have an integer pointer ip which contains address 1000, then on incrementing it by 1, we will get 1004 (i.e 1000 + 1*4) instead of 1001 because the size of the int data type is 4 bytes. If we had been using a system where the size of int  is 2  bytes then we would get 1002 ( i.e 1000 + 1*2 ).

Similarly, on decrementing it we will get 996 (i.e 1000 - 1*4) instead of 999. So the expression ip + 4 will point to address 1016 (i.e 1000 + 4*4 ).

Let's take some more examples.

int i = 12, *ip = &i;
double d = 2.3, *dp = &f;
char ch = 'a', *cp = &ch;

Suppose the address of i, d and ch are 1000, 2000 , 3000 respectively, therefore ip, fp and cp are at 1000, 2000, 3000 initially.

Pointer arithmetic on integers

Pointer expression Final value of variable ip
ip = ip + 1 ip => ip + 1 => 1000 + 1*4 => 1004
ip++ or ++ip ip++ => ip + 1 => 1004 + 1*4 => 1008
ip = ip + 5 ip => ip + 5 => 1008 + 5*4 => 1028
ip = ip - 2 ip => ip - 2 => 1028 - 2*4 => 1020
ip--  or --ip ip => ip + 2 => 1020 + 2*4 => 1028

Pointer arithmetic on float

Pointer expression Final value of dp
dp + 1 dp = dp + 1 => 2000 + 1*8 => 2008
dp++  or ++dp dp++ => dp+1 => 2008+1*8 => 2016
dp = dp + 5 dp => dp + 5 =>2016+5*8 => 2056
dp = dp - 2 dp => dp - 2 => 2056-2*8 => 2040
dp--  or --dp dp => dp - 1 => 2040-1*8 => 2032

 Pointer arithmetic on characters

Pointer expression Final value of cp
cp + 1 cp = cp + 1 => 3000 + 1*1 => 3001
cp++ or ++cp cp => cp + 1 => 3001 + 1*1 => 3002
cp = cp + 5 cp => cp + 5 => 3002 + 5*1 => 3007
cp = cp - 2 cp => cp + 5 => 3007 - 2*1 => 3005
cp-- or --cp cp => cp + 2 => 3005 - 1*1 => 3004

Note: When we increment or decrement pointer variables using pointer arithmetic then, the address of variables i, d, ch are not affected in any way. 

Arithmetic operation on type char seems like ordinary arithmetic because the size of char type is 1 byte. Another important point to note is that when we increment and decrement pointer variable by adding or subtracting numbers then it is not necessary that the pointer variable still points to a valid memory location. So, we must always pay special attention when we move the pointer in this way. Generally, we use pointer arithmetic with arrays because elements of an array are arranged in contiguous memory locations , which is discussed in detail in the next chapter.

The following program shows pointer arithmetic.

#include<stdio.h>

int main()
{
    int i = 12, *ip = &i;
    double d = 2.3, *dp = &d;
    char ch = 'a', *cp = &ch;

    printf("Value of ip = %d\n", ip);
    printf("Value of dp = %d\n", dp);
    printf("Value of cp = %d\n\n", cp);

    printf("Value of ip + 1 = %d\n", ip + 1);
    printf("Value of dp + 1 = %d\n", dp + 1);
    printf("Value of cp + 1 = %d\n\n", cp + 1);

    printf("Value of ip + 2 = %d\n", ip + 2);
    printf("Value of dp + 2 = %d\n", dp + 2);
    printf("Value of cp + 2 = %d\n", cp + 2);

    // signal to operating system program ran fine
    return 0;
}

Expected Output:

Value of ip = 2293316
Value of dp = 2293304
Value of cp = 2293303

Value of ip + 1 = 2293320
Value of dp + 1 = 2293312
Value of cp + 1 = 2293304

Value of ip + 2 = 2293324
Value of dp + 2 = 2293320
Value of cp + 2 = 2293305

Pointer arithmetic between two pointers

If we have two pointers p1 and p2 of base type pointer to int with addresses 1000 and 1016 respectively, then p2 - p1 will give 4 , since the size of int type is 4 bytes. If you subtract p2 from p1 i.e p1 - p2 then answer will be negative i.e -4.

The following program demonstrates pointer arithmetic between two pointers of the same type.

#include<stdio.h>

int main()
{
    int i1 = 12, *ip1 = &i1;
    int i2 = 12, *ip2 = &i2;

    printf("Value of ip1 or address of i1 = %u\n", ip1);
    printf("Value of ip2 or address of i2 = %u\n\n", ip2);

    printf("ip2 - ip1 = %d\n", ip1 - ip2);
    printf("ip1 - ip2 = %d\n", ip2 - ip1);

    // signal to operating system program ran fine
    return 0;
}

Expected Output:

Value of ip1 or address of i1 = 2686788
Value of ip2 or address of i2 = 2686780

ip2 - ip1 = 2
ip1 - ip2 = -2

Combining indirection operator (*) and increment/decrement operator

While processing elements of an array (as you will see in the next chapter) C programmers often mix indirection operator (*) and increment/decrement operator( ++ and -- ).

Always remember that the precedence of indirection operator (*) and increment/decrement operator are same and they associate from right to left.

Suppose x is integer variable and p is a pointer to int. Now consider the following statements and try to interpret them.

Example 1:

x = *p++;

Since * and ++ operators have the same precedence and associate from right to left ++ will be applied to p not to *p. Because the increment operator is postfix, so first the value of p is used in the expression then it will be incremented. Therefore first integer pointed by p will be dereferenced and assigned to x, then the value of p will be incremented by 1.

Example 2:

x = ++*p;

Here * operator will be first applied to p then ++ will be applied to *p. Therefore first integer pointer is dereferenced, the value obtained from dereferencing is incremented and eventually assigned to x.

Example 3:

x = *++p;

++ operator is prefixed, so first, p will be incremented, then the value at the new address is dereferenced and assigned to x.

Note: If you still have any confusion, you can always use () around expression which you want to evaluate first.

Pointer Comparison

You can use relational operators ( <, <=, >, >= , == , !=) with pointers. The == and != operators are used to compare two pointers whether they contain the same address or not. Two pointers are equal when they both are null, or contains the address of the same variable. Use of these(i.e == and !=) operators are valid only when pointers are of the same base type, or between a null pointer and any other pointer, or void pointer(will be discussed later) and any other pointer. Use of other relational operators (<, <=, >, >=) to compare two pointers is meaningful only when they both point to the elements of the same array.

Pointer to pointer

As we know the pointer is a variable that contains the memory address. The pointer variable itself occupies some space in memory and hence it also has a memory address. We can store the address of pointer variable in some other variable, which is known as pointer to pointer. The syntax of declaring pointer to pointer is as follows:

Syntax: data_type **p;

Let’s take an example:

int i = 10;
int *ip = &i;
int **iip = &ip;

Here ip  is of type (int *) or pointer to int, iip is of type (int **) or pointer to pointer to int.

We know that *ip will give value at address ip i.e value of i. Can you guess what value will **iip will return ?

**iip

We know that indirection operator evaluated from right to left so **iip can also be written as

*(*iip)

*iip means value at address iip or address stored at ip. On dereferencing address stored at ip we will get the value stored in the variable i.

*(*iip)
=> *ip
=> i

Therefore **iip gives the value stored in the variable i.

The following program demonstrates how to use pointer to pointer in int.

#include<stdio.h>

int main()
{
    int i = 10;
    int *ip = &i;
    int **iip = &ip;

    printf("Value of i = %d\n\n", i);

    printf("Address of i = %u\n", &i);
    printf("Value of ip = %d\n\n", ip);

    printf("Address of ip = %u\n", &ip);
    printf("Value of iip = %d\n\n", iip);

    printf("Value of *iip = value of ip = %d\n", *iip);
    printf("Value of **iip = value of i = %d\n\n", **iip);

    // signal to operating system program ran fine
    return 0;
}

Expected Output:

Value of i = 10

Address of i = 2293332
Value of ip = 2293332

Address of ip = 2293320
Value of iip = 2293320

Value of *iip = value of ip = 2293332
Value of **iip = value of i = 10