Pointers in C

In this section of the tutorial, we will discuss a very important and powerful feature of C programming language, i.e. Pointers.

Pointers are extensively used in C because it provides flexibility in writing programs.

In this tutorial, we will study the Pointers in detail with program examples for better understanding.

Now, let’s start with the introduction of Pointers.

What are Pointers?

A Pointer is a derived data type in C that stores the address of another variable. A Pointer contains memory addresses as their values. Pointers can be used to assign, access, and manipulate data values stored in the memory allotted to a variable since it can access the memory address of that variable. It is one of the most powerful and distinct features that C programming language offers to its users.

  • Here, the value in variable p is the address of the variable Marks.
  • We can access the value of variable Marks by using the value of variable p.
  • Hence, we can say that variable p points to the variable Marks. Thus, variable p is a pointer variable.
  • The values of variable p and variable Marks can be different after each program run.

To understand the concept of Pointers, we need to know the three elemental divisions of Pointers, that are:

  • Pointer Constants
  • Pointer Values
  • Pointer Variables

The above three divisions are basically the very underlying concepts behind the creation of Pointer in C.

Let’s discuss each one of them that will eventually help in understanding Pointers in depth.

Pointer Constants

Pointer Constants is referred to as the memory address of a variable. They cannot be changed. They can only be used to store data values in the variable. We can think of they are ‘house numbers’ to understand its purpose.

Pointer Values

Memory addresses cannot be saved directly. It can only be saved through the address of the variable using the address operator (&). This value that is obtained is called Pointer Values. Pointer Values (i.e. the address of a variable) may change after different running intervals of the program.

Pointer Variables

Pointer Variables are such variables that store the Pointer Value (i.e. address of another variable).

Advantages of using Pointers

Pointers are so useful that it is the most frequently used feature in C, because of its numerous advantages.
Some of them are listed below:

  • Pointers are most efficient in handling arrays and other data structures.
  • Pointers can return multiple values from a function through function arguments.
  • Pointers can be used to reference a function and hence it enables passing of a function as an argument to another function.
  • Pointers save a lot of space in storage memory by offering the use of pointer arrays to character strings.
  • Pointers support dynamic memory allocation in C.
  • Pointers enables a user to manipulate dynamic data structures such as linked lists, queues, stacks, and trees.
  • Pointers drastically reduce the complexity and length of a program.
  • Pointers help in reducing the execution time by increasing the execution speed of a program.

How to declare Pointer variables?

Now, before we start using Pointers in our program. We must understand how to initialize it in a program.

Pointers store the address of a variable of a particular data type. So they must also be declared with a data type before we start using them.
The general form of declaring a Pointer Variable is:

data_type *pt_name;

  • Here, data_type is the data type of the variable pt_name is pointing towards.
  • The asterisk*‘ specifies that pt_name is a pointer variable.
  • It tells the compiler that pt_name needs a memory location.

Example:

int *p;

float *n;

  • Here, p is a pointer variable that points to an integer data type. This data type refers to the data type of the variable that p is pointing towards.
  • Also, n is a pointer variable that points to a float data type.
  • This data type again refers to the data type of the variable that p and n are pointing towards.
  • Both the pointers p and n will be assigned a memory location otherwise they will contain garbage values.

Other methods of declaring a pointer variable are:

Type 1: int *p;

Type 2: int* p;

Type 3: int * p;

Type 1 is more suitable when we have multiple declarations in one statement like: int *p, x, *q;

How to initialize Pointer variables?

In initializing a pointer variable, we assign the address of a variable to the pointer variable.

Once a pointer variable is declared, we can initialize it using the assignment operator.

Example:

int Marks;

int *p; (Declaration)

p = &Marks; (Initialization)

We can also declare and initialize a pointer variable together:

int *p = &Marks;

[Important point: The data type of the variable and the pointer variable should be the same.]

How to access a variable through its Pointer?

Till now, we know that we can access the value of a variable by the address of the variable using address operator ‘&’. We have used it several times in almost every program in the previous topics. Example: scanf(“%d”,&Marks);

Now, we will learn how we can use a pointer to access the value of a variable.

We use unary operator ‘*’ an asterisk (also known as indirection operator or dereferencing operator) to access the address of a variable to ultimately access the stored data value.

Example:

int Marks, *p, n;

Marks = 85;        

p = &Marks;      

n = *p;                 

  • Here, the first line has declaration of variables (i.e. Marks and n) and pointer variable (i.e. p)
  • In the second line, variable Marks is assigned with a value 85 in it.
  • In the third line, the pointer variable p is assigned with the address of the variable Marks.
  • In the fourth line, variable n is assigned with the value of at the address assigned to variable p by using asterisk ‘*’ before variable p (i.e. *p). It means using asterisk ‘*’ with the pointer variable p returns the value stored at variable Marks.

Below is an example to demonstrate how we can access a variable through its Pointer.

Example: Program to illustrate the use of indirection operator ‘*’.

Code:

#include<stdio.h>
int main()
{
    int x=2,y;
    int *ptr;
    ptr = &x;
    y = *ptr;
    printf("Value stored in x is %d\n",x);
    printf("Address of %d is %u\n",x,&x);
    printf("Address of %d is %u\n",*&x,&x);
    printf("Address of %d is %u\n",*ptr,ptr);
    printf("Address %d is stored at %u\n",ptr,&ptr);
    printf("Address of %d is %u\n",y,&y);
    *ptr = 25;
    printf("Now the value stored in x is %d\n",x);
    return 0;
}

Output:

Value stored in x is 2
Address of 2 is 890966264
Address of 2 is 890966264
Address of 2 is 890966264
Address 890966264 is stored at 890966272
Address of 2 is 890966268
Now the value stored in x is 25

What is chain of Pointers?

Chain of pointers is created when we make a pointer to point to another pointer and it may continue further.

Here, pointer variable p2 contains the address of the pointer variable p1, which contains the address of the original variable having the desired data value. This is known as multiple indirections.

A pointer that points to another pointer must be declared with an extra unary operator (i.e.’*’ an asterisk).

Example:

int **p2;

  • Here, pointer variable p2 points to another variable p1 of type int.

We can access the target value through chain of operators by applying indirection operator ‘*’ twice.

Example:

main()

{

   int x, *p1, **p2;

   x = 100;

   p1 = &x;

   p2 = &p1;

   printf(“%d”, **p2);

}

  • Here, p1 is declared as pointer to an integer and p2 as a pointer to a pointer to an integer.
  • Hence, the output will be value 100 stored in variable x.

How to use Pointer expressions?

Like normal variables, pointer variables can also be used in expressions.

Example:

y = *p1 * *p2;

sum = sum + *p1;

z = 5* – *p2/ *p1;

*p2 = *p2 + 10;

  • Here, in line 1, *p1 * *p2; can also be declared as (*p1) * (*p2);
  • In line 3, 5* – *p2/ *p1; can also be declared as (5 * (- (*p2))) / (*p1);
  • Also, there is a space between / and *, which is important to be there otherwise compiler will take it as a comment(/*).

Arithmetic Operations of Pointers

In C programming language, we can add or subtract integers from a pointer and we can subtract one pointer from another pointer too. Example: p1 + 4, p2 – 2, and p1 – p2.

We can also use other operators with pointers, for example:

p1++;

-p2;

sum += *p2;

p1 > p2

p1 == p2

p1 != p2

But we cannot multiply or add two pointers, for example: p1 * p2 and p1 + p2 are not allowed.

Below is an example to demonstrate how we can use Pointers in expressions.

Example: Program to illustrate the use of Pointers in arithmetic operations.

Code:

#include<stdio.h>
int main()
{
  int a=8,b=5,x,y,z,*p1,*p2;
  p1 = &a;
  p2 = &b;
  x = *p1 * *p2 - 3;
  y = 4* - *p2 / *p1 + 5;
  printf("Address of a is %u\n",p1);
  printf("Address of b is %u\n",p2);
  printf("a is %d, b is %d, x is %d, y is %d\n",a,b,x,y);
  *p2 = *p2 + 3;
  *p1 = *p1 * *p2 - 6;
  z = *p1 * *p2 - 6;
  printf("a is %d, b is %d, z is %d\n",a,b,z);
  return 0;
}

Output:

Address of a is 3576265156
Address of b is 3576265160
a is 8, b is 5, x is 37, y is 3
a is 58, b is 8, z is 458

Increment in Pointers

Increment in pointers is possible, like p1++; but the increment of the pointer will be relative to the length or size of the data type that it points to.

Example:

int *p1;

p1++;

  • Here, p1 is a pointer variable pointing to a variable of type int. p1 is incremented using increment operator (++), its value will increase relative to the length or size of the data type integer which is 4 bytes.
  • So, if the initial value of p1 is 1002, then after the operation p1++, the value will become 1006.

Pointers and Arrays

Pointers prove to be very useful for accessing elements present in an Array through the address of each cell of Array.

  • When an Array is declared, sufficient memory is allocated for the storage of all the Array elements in contiguous memory locations.
  • Also, after an Array is declared, a base address is allocated to the first element of the Array (index value 0).
  • An Array name is also defined as a constant pointer to the first element.

Example:

int x[5] = {1,2,3,4,5};

Let’s say, the base address of the first element of x (x[0] = 1) is 3000, now since Array is of type int, each integer will require 4 bytes.
So, the elements will be stored in a way like this:

The name x is defined as a pointer constant pointing to the first element of Array i.e. x[0], therefore the value of pointer constant x is 3000 (address of x[0]).

x = &x[0] = 3000

Now, if we declare p as an integer pointer to point to the Array x,

p = x;
or
p = &x[0];

Now, we can access every value of constant pointer x using the increment operator (++) with integer pointer p by moving from one element to another through increasing the addresses.

p = &x[0] (= 3000)
p+1 = &x[1] (= 3002)
p+2 = &x[2] (= 3004)
p+3 = &x[3] (= 3006)
p+4 = &x[4] (= 3008)

Now, finally we can access every value present in the origin of Array elements using:

*(x+i) or *(p+i)

*x = 1  or *p = 1
*(x+1) = 2 or *(p+1) = 2
*(x+2) = 3 or *(p+2) = 3
*(x+3) = 4 or *(p+3) = 4
*(x+4) = 5 or *(p+4) = 5

Below is an example to demonstrate how we can access Array elements using the Pointer.

Example: Program to find the sum of all the elements of an Array using Pointers.

Code:

#include<stdio.h>
int main()
{
    int *p,sum=0,i=0;
    int x[3]={1,3,5};
    p = x;
    while (i<3)
    {
        printf("Value of element x[%d] is %d stored at address %d.\n",i,*p,p);
        sum = sum + *p;
        i++;
        p++;
    }
    printf("Sum of all the elements is %d.\n",sum);
    return 0;
}

Output:

Value of element x[0] is 1 stored at address 181672540.
Value of element x[1] is 3 stored at address 181672544.
Value of element x[2] is 5 stored at address 181672548.
Sum of all the elements is 9.

Similarly, an element in a two-dimensional Array can be accessed by the following pointer expression:

*(*(x+i)+j) or *(*(p+i)+j)

Suppose, the elements are stored in a way like this:

  • Here, i represents row and j represents column in a two-dimensional Array x[i][j].
  • Also, p is an integer pointer pointing to Array x with the initial address of &x[0][0].
  • Hence, x[i][j] becomes equivalent to *(p+4 x i+j).
  • Example: For element x[2][3], we can also use *(p+4 x 2+3) = *(p+11).

So, we must specify the size of each row so that the compiler determines the correct storage mapping.

Pointers and Functions

Pointers can be used to carry out a task of Function which involves continuous accessing, modifying, and evaluating value present in variables.

A pointer can be used to pass the address to functions, return pointer variable from a function, and to declare pointers to functions. Each one of these abilities of Pointers is discussed in a separate heading below.

Passing address to Functions

We can pass the address of a variable as an argument to a function. We have used this method in returning multiple values in Function in C section in the previous parts of the tutorial.

In calling a function, we can use two methods to pass the values of a variable to a function definition from the function call.
Below are those two methods discussed.

The function which is called by reference can modify the values of variables used in the call. This method is also known as call by address or pass by pointers.

Now, we will study an example to understand how the addresses of variables are passed to a function using pointers to change the values of these variables stored in two different locations in the memory.

Example: Program to swap values of two variables using pointer operation.

Code:

#include <stdio.h>  
void swap(int * , int *); 
int main()  
{  
    int x = 2;  
    int y = 4;   
    printf("x is %d and y is %d before swapping\n",x,y);

    swap(&x,&y);
      
    printf("x is %d and y is %d after swapping\n",x,y);
    return 0;
}  
void swap (int *x, int *y)  
{  
    int temp;   
    temp = *x;  
    *x=*y;  
    *y=temp;
}

Output:

x is 2 and y is 4 before swapping
x is 4 and y is 2 after swapping

Returning Pointers from Functions

In the Functions in C section of this tutorial, we have learnt that a Function can return a single value by its name. And also it can return multiple values through pointer parameters.

In C programming language, we can return a Pointer from the Function definition to the calling Function. We will understand the working of such a program through an example:

Example: Program to find a larger number between two numbers.

Code:

#include<stdio.h>
int *Large(int *, int *);

int main()
{
  int a=5,b=10,*p;

  p = Large(&a,&b);
  
  printf("Larger number between %d and %d is %d.",a,b,*p);
}
int *Large(int *x, int *y)
{
  if(*x>*y)
    return (x);
  else
    return (y);  
}

Output:

Larger number between 5 and 10 is 10.

Declaring Pointers to Functions

Like a normal variable, a Function too has a type and an address location in the memory. So it is allowed to declare a pointer to a function, that can be used as an argument in other functions.

A pointer to function can be declared as: type (*ptr) ();

  • Here, ptr is a pointer to function which return type value.
  • The parentheses around *ptr are necessary otherwise it will mean that the function is returning a pointer to type.

We can assign a name of a function to the pointer to make the function pointer point to that specific function.
Example:

int Mul(int , int);
int (*p1) ();
p1 = Mul;

  • Here, p1 is declared as pointer to function.
  • And Mul is declared as the function.
  • Then, p1 is made to point to function Mul.

Now, to call function Mul, pointer p1 can be used.
Example:

[Pointer to Function Call]
(*p1) (x, y)

or
[Normal Function Call]
Mul(x, y)

We will understand how we can use a pointer to function with the help of an example.

Example: Program to find the multiple of two numbers using Pointer to Function.

Code:

#include<stdio.h>
int Mul(int ,int);

int x;
int main()
{
    int a=10,b=5;

    int (*p1) (int, int);

    p1 = Mul;

    (*p1)(a,b);

    printf("Multiplication of %d and %d is %d.",a,b,x);

    return 0;
}
int Mul(int a, int b)
{
    x=a*b;

    return (x);
}

Output:

Multiplication of 10 and 5 is 50.