Pointers in 'C'


Pointers in 'C' language :
Definition :
  • Pointer is a variable which stores address of another variable. Data type of a pointer determines data type of a variable whose address is being stored by a pointer.
  • For example pointer of type integer will store address of integer variable. Float pointer will store address of float variable and so on.

Declaration :
  • To declare a variable as a pointer indirection operator (*) is used.
  • Syntax :
         data_type *ptr_name;
  • Example int *p;
 It indicates that variable p will point to      an integer variable or p will store an address of integer variable. 
  • Address of operator(&) will returns address of a particular variable.


Initialization :
  • Similar to other variables pointer variable can be initialized either at the time of a declaration or after declaration.
  • For example int age=45;
        int *p=&age;
                Or
        int age=45,*p;
        p=&age;
  • Here &age will return address of memory location where value of age is stored and that address will get assigned to a pointer variable p.
  • To be more clear assume that value of age stored at address 1001 then p will stored 1001 as its value.


Dereferencing :
  • Deferencing is a process of obtaining value stored at addresses pointed by pointer.
  • It is a way accessing values pointed by pointer.
  • Asterisk symbol (*) called dereferencing operator is used for this purpose.
  • For example :
       int age=45,*p;
       p=&age;
       printf("%d",*p);
Will print value 45.
  • Assume address of age as 1001.* refers to the content of thus *p is equivalent to *(&age) which is equivalent to *(1001) so this will be content of memory location with address 1001. Hence the result is 45.


  • To understand pointers consider following program:

#include<stdio.h>
int main()
 {
 int *p,age=45;
 p=&age;
//understanding pointers
 printf("\n Address of variable age = %d",&age);
 printf("\n Value of pointer p = %d",p);
 printf("\n value of age = %d",age);
 printf("\n Dereferencing pointer results in %d",*p);

 return 0;
}

Output :
 Address of variable age = 1730727020
 Value of pointer p = 1730727020
 value of age = 45
 Dereferencing pointer results in 45

Note : Here we can see address of 'age' and value of pointer 'p' is same. Thus it is clear that 'p' stores address of 'age'.


Pointer Arithmetic :
  • As pointer stores address of another variable value of pointer is always numeric.
  • Thus we can perform all arithmetic operations like increment(++), decrement   (--),addition(+),subtraction (-) along with comparison operations (<,<=,>,>=) that we can perform on integers.
  • We should remember that incrementing pointer will point to next memory location and decrementing pointer will point to previous memory location.
  • Also if system is of 32 bit using 2 bytes to store integer and pointer is pointing to an integer variable then result of arithmetic operations will be in respective proportion.
  • To be more clear let's see example : 
1) Program to perform arithmetic operations on pointer

#include<stdio.h>
int main()
{
 int *p,age=45;
 p=&age;
 printf("\n Address of variable age = %d",&age);
 printf("\n Value of pointer p = %d",p);
 //pointer arithmetic
 p++;
 printf("\n After incrementing pointer value is =%d",p);
 p--;
 printf("\n After decrementing pointer value is =%d",p);
 p=p+2;
 printf("\n On Addition of 2 pointer value is =%d",p);
 p=p-4;
 printf("\n On subtraction of 4 pointer becomes %d",p);
 printf("\n now pointer is pointing to %d",*p);
 return 0;
}

Output :
 Address of variable age = 237936684
 Value of pointer p = 237936684
 After incrementing pointer value is =237936688
 After decrementing pointer value is =237936684
 On Addition of 2 pointer value is =237936692
 On subtraction of 4 pointer becomes 237936676
 now pointer is pointing to 22013

Note : Since using 64 bit system after increment that is by adding 1 to pointer value is increased by 4 byte and similar for all operations.

2) Program to illustrate comparison of two pointers 

#include<stdio.h>
int main()
{
 int *p,*q,age=45,salary=15000;
 p=&age;
 q=&salary;

 printf("\n Value of pointer p = %d",p);
 printf("\n Value of pointer q = %d",q);
 //Comparing pointers
 if(p<q)
 printf("\n p is less than q");
 else
 printf("\n p is greater than q");

 return 0;

}

Output :
 Value of pointer p = 1384553824
 Value of pointer q = 1384553828

 p is less than q

Note : we have successfully compared value of two pointers.

Pointer to Array :

  • We can declare pointer to whole array as 
data_type *(ptr_name)[size_of_arr]=&arr_name;

  • Size of pointer is always fixed it is 8 bytes in C.
  • If we declare pointer of array of size 5 then size of pointer will be 8*5=40. Since array is pointing to 5 elements.
  • Let's see program to illustrate size of array:

#include<stdio.h>
int main()
{
 char *c;
 int *p;
 //declaring array of pointers
 int *ptr[5];
 printf("\n size of p = %d",sizeof(p));
 printf("\n size of ptr = %d",sizeof(ptr));
 printf("\n size of c = %d",sizeof(c));
 return 0;
}

Output :
 size of p = 8
 size of ptr = 40
 size of c = 8

2) Program to illustrate pointer to array

#include<stdio.h>
int main()
{
 int *p;
 // Pointer to an array of 5 integers
 int (*ptr)[5];
 int num[5];
 // Points to 0th element of the arr.
 p = num;   //or p=&num[0];
 // Points to the whole array arr.
 ptr = &num;
 printf("p = %d, ptr = %d\n", p, ptr);
 p++;
 ptr++;
 printf("p = %d, ptr = %d\n", p, ptr);
 return 0;
}

Output : 
p = 0x7ffcc5cdc4e0, ptr = 0x7ffcc5cdc4e0

p = 0x7ffcc5cdc4e4, ptr = 0x7ffcc5cdc4f4

Note : From the output it is clear that pointer to array and pointer to zeroth element of array is different.

Array of Pointers : 
  • We can also declare an array which stores pointer variables in it called as array of pointers.
  • Syntax :
data_type * arr_name[size];
  • For example int *ptr[5];  Here or is an array of a pointers which will store values of five pointer variables in it.
  • Consider following program:

#include<stdio.h>
int main() {
 int *p,i; 
 //declaring array of pointers
 int *ptr[5]; 
 int num[5]={10,20,12,45,67};
 for(i=0;i<5;i++)
 //assigning values to pointer array
 ptr[i]=&num[i];
 printf("\n Pointer points to:\n");
 for(i=0;i<5;i++)
 printf("\n value at num[%d] : %d",i,*ptr[i]);
 return 0;
}

Output :
 Pointer points to:
 value at num[0] : 10
 value at num[1] : 20
 value at num[2] : 12
 value at num[3] : 45
 value at num[4] : 67

Pointer to Pointer/ Double pointer :
  • A pointer variable which stores address of another pointer variable as its value is called pointer to pointer or double pointer.
  • Size of double pointer is also 8 byte in C.
  • Double asterisk (**) symbol is used to declare double pointer.
  • Syntax : data_type **ptr_name;
  • Consider following program to illustrate double pointer 
#include<stdio.h>
int main()
{
 int num=45;
 int *p,**q;
 //q is double pointer
 p=&num;
 q=&p;//q pointing to pointer p
 printf("\n size of p =%d",sizeof(p));
 printf("\n size of q=%d ",sizeof(q));
 printf("\n Address of p= %d",&p);
 printf("\n Value pointed by p =%d",*p);
 printf("\n Value pointed by q=%d",*q);
 printf("\n Using double pointer dereferencing value =%d",**q);
 return 0;
}

Output :
 size of p =8
 size of q=8 
 Address of p= -611173832
 Value pointed by p =45
 Value pointed by q=-611173836
 Using double pointer dereferencing value =45
Note : Output shows that double pointer 'q' stores address of another pointer 'p'.

Pointer and Function :
  • We can pass pointer to a function as an argument.
  • In this case we should use call by reference while calling function.
  • Also function will affect actual values of arguments.
  • Example: Consider following program to exchange values of two variables 

#include<stdio.h>
int main()
{
 int a=20,b=50;
 //passing pointer to function
 int swap(int *a,int *b)
 {
 int t;
 //swapping values
 t=*a;
 *a=*b;
 *b=t;
 }
 printf("\n before calling function value of a=%d and b=%d",a,b);
 swap(&a,&b);
 printf("\n After calling function values are a=%d and b=%d",a,b);
 return 0;
}

Output :
 before calling function value of a=20 and b=50
 After calling function values are a=50 and b=20

  • Similarly we can also define a function that returns pointer value from it.
  • Example  : Consider following program for addition of two integers 

#include<stdio.h>
int main()
{
 int a=20,b=50;
 int *result;
 //returning pointer from function
 int *addition(int a,int b)
 {
 int *t,add;
 add=a+b;
 t=&add;
 return t;
 }
 result=addition(a,b);
 printf("\n Aaddition = %d",*result);
 return 0;
}

Output :
 Aaddition = 70


Dynamic  Memory Allocations :
  • Dynamic memory  allocation is a process of allocating memory to a variables on run time when values get assigned to them. 
  • C language provides a way to allocate memory at run time by using standard memory allocation functions. 
  • These functions are resides in stalib.h header file. 
  • Thus in order to use these functions we must include stdlib.h file in our program. 
  • There are in all four functions that deals with dynamic memory allocation : malloc, calloc, realloc and free.

1) malloc : 
  • malloc stands for memory allocation. 
  • This function allocates memory in the form of single large block and returns a pointer pointing to that memory. 
  • Syntax : ptr = (cast_data_type*) malloc(size in bytes);
  • For example p=(int*) malloc(5*size of(int)); will allocate memory size of 5 integers that is 20 bytes on runtime and returns pointer to it.
  • Consider following program to allocate memory to n integers dynamically :

#include<stdio.h>

#include<stdlib.h>
int main()
{
 int n,*ptr,i;
 printf("\n Enter how many integers: ");
 scanf("%d",&n);
 //creating memory allocation dynamically 
 ptr=(int*) malloc(n*sizeof(int));
 for(i=0;i<n;i++)
 {
 printf("\n Enter element%d : ",i);
 scanf("%d",&ptr[i]);
 }
 //displaying values
 printf("\n You entered :\n");
 for(i=0;i<n;i++)
 printf("%d\t",ptr[i]);
return 0;
}

Output :
 Enter how many integers: 5
 Enter element0 : 10
 Enter element1 : 20
 Enter element2 : 30
 Enter element3 : 40
 Enter element4 : 50
 You entered :
10 20 30 40 50


2) calloc : 
  • calloc stands for contiguous allocation of memory. 
  • It allocates specified size of memory at contiguous blocks. 
  • This function also returns a pointer pointing to first address of block. 
  • Syntax : (cast_type*) calloc(n,sized element in bytes); where n states how many elements. 
  • For example ptr=(int*)calloc(5,sizeof(int)); will allocate memory for 5 integers that is 20 bytes of memory. 
  • Program to illustrate calloc :


#include<stdio.h>

#include<stdlib.h>
int main() 
{
 int n,*ptr,i;
 printf("\n Enter how many integers: ");
 scanf("%d",&n);
 //creating memory allocation dynamically 
 ptr=(int*) calloc(n,sizeof(int));
 for(i=0;i<n;i++)
 {
 printf("\n Enter element%d : ",i);
 scanf("%d",&ptr[i]);
 }
 //displaying values
 printf("\n You entered :\n");
 for(i=0;i<n;i++)
 printf("%d\t",ptr[i]);
return 0;
}

Output :
 Enter how many integers: 5
 Enter element0 : 45
 Enter element1 : 15
 Enter element2 : 12
 Enter element3 : 65
 Enter element4 : 80
 You entered :
45 15 12 65 80

3)realloc : 
  • realloc stands for reallocation of memory. 
  • This function allows to change size of previously dynamically allocated memory either by using calloc or malloc. 
  • Syntax : ptr=realloc(ptr,new_size);
  • Program to illustrate use of realloc

#include<stdio.h>

#include<stdlib.h>
int main() 
{
 int n,*ptr,i;
 printf("\n Enter how many integers: ");
 scanf("%d",&n);
 //creating memory allocation dynamically 
 ptr=(int*) malloc(n*sizeof(int));
 printf("\n reallocating memory...\n");
 n=7;
 ptr=realloc(ptr,n*sizeof(int));
 printf("\n Reallocated memory successfully enter 7 integers\n ");
 for(i=0;i<7;i++)
 {
 printf("\n Enter element%d : ",i);
 scanf("%d",&ptr[i]);
 }
 //displaying values
 printf("\n You entered :\n");
 for(i=0;i<7;i++)
 printf("%d\t",ptr[i]);
return 0;
}

Output :
 Enter how many integers: 5
 reallocating memory...
Reallocated memory successfully enter 7 integers
 Enter element0 : 45
 Enter element1 : 15
 Enter element2 : 12
 Enter element3 : 65
 Enter element4 : 80
 Enter element5 : 78
 Enter element6 : 89
You entered :
45    15     12     65    80     78     89

4) free: 
  • free function is memory deallocating function. 
  • Above three functions does not deallocate memory allocated by them on it's own. 
  • Thus free() is used to deallocate memory allocated by using either malloc,calloc or realloc. 
  • Syntax : free(ptr); where ptr is a pointer returned by either malloc, calloc or realloc.
  • Program to illustrate free() :

#include<stdio.h>
#include<stdlib.h>
int main() 
{
 int *ptr;
 //creating memory allocation dynamically 
 ptr=(int*) malloc(sizeof(int));
 printf("\n Memory allocated...\n");
 *ptr=45; //assigning value
 printf("\n ptr contains =%d",*(ptr));
free(ptr);
 printf("\n Freed memory successfully\n ");
 printf("ptr contains=%d",*(ptr));
return 0;
}

Output :
 Memory allocated...
 ptr contains =45
 Freed memory successfully
 ptr contains=0

Note : Since memory is deallocate ptr does not contain value 45 as it is freed.

Memory leak :

  • If programmer uses memory resource inefficiently then it results into memory leak. 
  • It is a situation such that no appropriate memory is available to allocate for new data since memory is allocated previously to some data which is not useful now.


Dangling pointer : 

  • Pointer which is pointing to a value which has been deleted is called dangling pointer.
  • When we allocate memory to pointer dynamically and later deleted a value assigned to it without modifying ptr then ptr becomes dangling pointer. In above example of free() ptr contains=0 since 45 is deleted. 
  • That means ptr is still pointing to that memory hence it is dangling pointer.

Comments

Popular posts from this blog

Write a program to allocate memory dynamically for n integers. Accept the elements and calculate their sum and average

C program to accept names of n cities and search for city named “Pune”.