Wednesday, 2 January 2019

POINTERS


POINTERS

A pointer is a variable, which holds the address of another variable.

Advantages of pointers
  • Pointers increases execution speed
  • Pointers reduces length & complexity of a program
  • Pointers access memory elements very easily
  • Use of pointers to string saves storage space in memory
  • Pointers help to return more than one value from function
  • Pointers saves memory by using Dynamic Memory Allocation
  • Pointers are very useful in Data Structure Manipulation

Address Operator (&) and Value at / indirection operator (*)

All the variables including pointer variables defined in a program reside at specific address. It is possible to obtain the address of a variable by using the address operator &(ampersand). When we place ‘*’ before the pointer variable it accesses the contents of the variable whose address is assigned to it.

Example:

#include<stdio.h>
#include<conio.h>
void main()
{
          int i=7;
          float f=10.5;
          char c='A';
          clrscr();
          printf("%d is stored at address %u\n",i,&i);
          printf("%.2f is stored at address %u\n",f,&f);
          printf("%c is stored at address %u\n",c,&c);
          getch();
}
Output:
7 is stored at address 65524
10.50 is stored at address 65520
A is stored at address 65519

Declaring and Initializing Pointers:

The declaration of a pointer variable is:
Syn:   Datatype *ptr_name
Ex:     int *p;
          Char *name;
          Float *ab;
Each one is intended to point to a different datatype.

Pointer Initialization:

int a=143;

int *p;          p is an integer pointer //Declaration
p=&a;                                       //initialization
          or
int *p=&a;    //initialization and declaration


*p=143
Value at p is 5000 i.e., address of a, now the value at address 5000 is 143.

Example 2
#include<stdio.h>
#include<conio.h>
void main()
{
          int *i;
          int v1=10,v2=20;
          clrscr();
          i=&v1;
          printf("Address and contents of var1 is %u and %d\n",i,*i);
          i=&v2;
          printf("Address and contents of var2 is %u and %d\n",i,*i);
          getch();
}
Output:
Address and contents of var1 is 65524 and 10
Address and contents of var2 is 65522 and 20

Value:                   10                20
Variable name:      V1               v2
Address:                65524 65522
I=&v1;          65524
*i=10           i.e., as i pointing to the v1 address value at that address is 10. hence the output
I=&v2;          65522
*i=20           i.e., as i pointing to the v2 address value at that address is 20. hence the output

Dereferencing pointers

Dereferencing is an operation performed to access and manipulates data contained in the memory location pointed to by a pointer. The operator * is used to dereference pointers.
Ex:
#include<stdio.h>
#include<conio.h>
void main()
{
          int *i;
          int v1,v2;
          clrscr();
          i=&v1;   //assigning the address of v1 to i
          *i=25;  
          *i+=10;        
          printf("var 1 contains %d\n",v1);
          v2=*i;
          printf("var 2 contains %d\n",v2);
          i=&v2;
          *i+=20;
          printf("var 2 now contains %d",v2);
          getch();
}
Output:
var 1 contains 35
var 2 contains 35
var 2 now contains 55    


Pointers to Pointers

We can also have pointers to pointers, just as we have pointers to integers.
Format:       datatype **ptr_name;

Ex:
main( )
{
          int x, *p1,**p2; //pointer to pointer (**p2)
          x=100;
          p1=&x;
          p2=&p1;
          printf(“%d”, **p2);
}

104
 

102
 

100
 
 



                 P2           P1              X
      106        104          102

Here, the p2 variable contains the address of pointer variable p1, which points to the location x that contains the desired value. This is known as multiple indirections. int **p2 is not an pointer to an integer, rather it is a pointer to an integer pointer.

Arithmetic Pointers

  1. Pointers can be incremented or decremented. When we increment a pointer it moves to the next location of its type. So,
    1. When a integer pointer is incremented, the change is +2
    2. When a character pointer is incremented, the change is +1
    3. When a float pointer is incremented, the change is +4
  2. If ptr1 & ptr2 are properly declared & initialized pointers, the following are valid:
res = res+ *ptr1;
*ptr1=*ptr2+5
Prod=*ptr1 * *ptr2;
Quo=*ptr1 / *ptr2;
          Any arithmetic operation can be performed on values at pointers
  1. Adding an integer or subtracting an integer from a pointer can be performed.
ptr1+2 or 2+ptr1    --    ptr1-2 or 2-ptr1 is valid
  1. Multiplication or division of a pointer with a constant is not allowed.  
ptr1*5 or ptr1/5 is invalid
  1. The only arithmetic operation that can be performed on pointers is subtraction i.e., to find the distance between the 2 pointers. The remaining arithmetic operations are not possible because it would not make any meaning.
p1-p2 is valid

Invalid operations
                   P1+p2  
                   P1*p2
P1/p2
                   P1*2  
                   P1/2

/* arithmetic operations on pointers */
#include<stdio.h>
#include<conio.h>
void main()
{
          int a=5,b=6;
          int *p1,*p2;
          clrscr();
          p1=&a;
          p2=&b;
          printf("p1=%u\tp2=%u\n",p1,p2);
          p1++;
          p2--;
          printf("Incrementation=%u\tDecrementation=%u\n",p1,p2);
          /* printf("Add=%u\n",p1+p2); invalid */
          /* printf("Mul=%u\n",p1*p2); invalid */
          /* printf("Div=%u\n",p1/p2); invalid */
          printf("Sub=%u\n",p1-p2);
          printf("Add with constant=%u\n",p1+2);
          printf("Sub with constant=%u\n",p1-2);
          /* printf("Mul with constant=%u\n",p1*2); invalid */
          /* printf("Div with constant=%u\n",p1/2); invalid */
          printf("Mul=%d\n",*p1**p2);
          printf("Div=%d\n",*p1 / *p2);
          printf("Add=%d\n",*p1 + *p2);
          getch();
}
Output:
P1=65496   p2=65498
Incrementation=65498    Dcrementation= 65496
Sub=1
Add with constant=65502
Sub with constant=65494
Mul=30
Div=1
Add=11

Arrays and Pointers

When an array is declared, the compiler allocates a base address and sufficient amount of space to contain all the elements of the array in memory locations.

Index
x[0]
x[1]
x[2]
x[3]
x[4]
Values
26
14
83
37
46
 Base Addresses
1000
1002
1004
1006
1008

x[0]=26
&x[0]=1000

Here the name x is defined as a constant pointer pointing to the base address i.e., first element.
For ex:         a=1000.



i=0;
value:
a[i]     // value at a[0] 26 *(a+i)  //value at position 1000+0->26
address:
&a[i]  pointing to a[0] 1000        (a+i)  pointing to (1000+0)=1000

Example:
#include<stdio.h>
#include<conio.h>
void main()
{
          int eno[10],n,i;
          int *e;
          clrscr();
          e=eno;          /*intializing with base address of empno*/
          printf("Enter the no of employees:");
          scanf("%d",&n);
          for(i=1;i<=n;i++)
          {
          printf("\nEnter the empno:");
          scanf("%d",(e+i));
          }
          for(i=1;i<=15;i++)
                   printf("=");
          printf("\n");
          for(i=1;i<=n;i++)
                   printf("Empno[%d]=%d\n",i,*(e+i));
          for(i=1;i<=15;i++)
                   printf("=");
          getch();
}
Output
Enter the no of employees:3
Enter the empno:101
Enter the empno:102
Enter the empno:103
===============
Empno[1]=101
Empno[2]=102
Empno[3]=103
===============
Pointers and 2-D arrays

//example
#include<stdio.h>
#include<conio.h>
void main()
{
          int a[2][2];
          int i,j;
          clrscr();
          printf("enter the elements:");
          for(i=0;i<2;i++)
                   for(j=0;j<2;j++)
                             scanf("%d",(*(a+i)+j));
          printf("The elements are:\n");
          for(i=0;i<2;i++)
          {
                   for(j=0;j<2;j++)
                             printf("%3d",*(*(a+i)+j));
                   printf("\n");
          }
          getch();
}
Output
Enter the elements:65 45 67 23
The elements are:
 65   45
 67   23
Array of pointers
An array of pointers is similar to an array of any predefined data type. As a pointer variable always contains an address, an array of pointers is a collection of addresses.
Example:
void main()
{
          int a[3]={1,2,3};
          int i, *p[3];
          clrscr();
          for(i=0;i<3;i++)
                   p[i]=a+i;
          for(i=0;i<3;i++)
                   printf("%u %u %d\n",&a[i],p[i],*(p[i]));
          getch();
}
Output
65520 65520 1
65522 65522 2
65524 65524 3

Example:
#include<stdio.h>
#include<conio.h>
void main()
{
          char *city[]={"vsp","chennai","hydbd","delhi"};
          int i;
          clrscr();
          for(i=0;i<4;i++)
          printf("%s\n",city[i]);
          getch();
}
Output
vsp
chennai
hydbd
delhi
Pointers to Strings
Pointers to strings are treated in a way similar to pointer to arrays of other data types. The name of the character array points to the base address of the string. The expression (arrayname+i) points to the ith char in the string. The expressions arrayname[i], i[arrayname], *(arrayname+i) contains the ith character of the string.
Example:
#include<stdio.h>
#include<conio.h>
void main()
{
          char city[]="visakhapatnam";
          int i=0;
          clrscr();
          while(*(city+i)!='\0')
          {
                   printf("%c %c %c\n",city[i],*(city+i), i[city]);
                   i++;
          }
          getch();
}

Example:
#include<stdio.h>
#include<conio.h>
void main()
{
          char *str[10][30];     //    size of str is 10 names having 30
characters each
          int n,i;
          clrscr();
          printf("How many strings u want to enter:");
          scanf("%d",&n);
          printf("\nEnter Strings:");
          for(i=0;i<n;i++)
          {        
                   fflush(stdin);
                   gets(str[i]);
          }
          printf("\n the entered strings are:\n");
          for(i=0;i<n;i++)
                   printf("%s\n",str+i);
          getch();
}
Output
How many strings u want to enter:3

Enter Strings:hyderabad
visakhapatnam
delhi
the entered strings are:
hyderabad
visakhapatnam
delhi
Pointers to Functions
Functions have addresses just like data items. The address of a function can be obtained by only specifying the name of the function without the parenthesis.

Declaration of a pointer to a function
return type (*ptr_variable) (functions args list);

Ex:
int test1(double)
int (*ptr) (double);
Here ptr is a pointer variable pointing to the function that returns an integer and takes a data item of type double as its argument. The pointer ptr can point either to the function test or test1. The expression *ptr replaces the function name in the declaration.
Example
#include<stdio.h>
#include<conio.h>
void func1(int i, float f)
{
          printf("i=%d f=%.2f\n", i,f);
}
void func2(char *s)
{
          printf("s=%s",s);
}
void main()
{
          void (*p)(int,float); //declaring ptrs to functions
          void (*q)(char *);
          int i=5;
          float f=10.5;
          char s[]="hai";
          clrscr();
          p=func1;  //assigning address of func1 to p
          q=func2;  //assigning address of func2 to q
          p(i,f);  //calling the function using ptrs
          q(s);
          getch();
}
Output
i=5 f=10.50
s=hai
Uses of function pointers
  1. in passing functions as arguments to other functions
  2. in writing viruses
  3. in implementation of dynamic binding