Wednesday, 8 January 2014

C Programming Language Tutorial XV – Pointer (malloc(), calloc(), pointer to function, dynamic memory allocation)

Pointer (*)
Pointer is a memory location which is always points to address of existing memory location. In short, pointer is a variable that points to another variable. Pointer is a special kind of variable that holds the memory address of another variable. Pointer does not hold data but it holds address of another variable.
Pointer Operators
*
It is unary operator enables the associated variable to become capable of storing address of another variable.
&
Returns the address of associated variable. It evaluates the address of its operand.
Use of Pointer
§ By using pointer we can access value directly through memory address.
§ It creates link between memory address hence changes made in one location directly gets reflected in another location.
§ To reflect more than one value from a function.
§ In memory management for dynamic memory allocation.
§ File pointers are very useful in file handling operations.
Declaration of Pointer
A pointer declaration consists of a base type, a *, and a variable name.
data-type *pointer-variable;
After declaration of pointer, it is very compulsory to initialize it with respective address of existing memory location. At a time a pointer is to point single location.
//program of introduction to pointer
#include<stdio.h>
#include<conio.h>
void main()
{
  int x=10,*p;  //p is a pointer variable
  clrscr();
 printf("Adress of  x = %u\n",&x);  //%u is used to print memory address
 printf("Addrss of pointer = %u\n",&p);
 p=&x;  //p points to address of x
 printf("Address of pointer after initialization = %u\n",p);
 printf("Value at address = %d\n",*p);   //*p is a value at address
 (*p)++; //increment to *p
 printf("After increment= %d",*p);
 getch();
 }
Output:
Adress of  x = 65524
Addrss of pointer = 65522
Address of pointer after initialization = 65524
Value at address = 10
After increment= 11
//program to compare pointer and general variable
#include<stdio.h>
#include<conio.h>
void main()
{
 int x=10,y,*p;
 clrscr();
 y=x;  //copy x to y
 printf("Value of x = %d\n",x);
 printf("Value of y = %d\n",y);
 x++;
 printf("\nValue after increment of x = %d\n",x);
 printf("Value after increment of y = %d\n",y);
 p=&x; //Pointer points to x
 printf("\nValue of x = %d\n",x);
 printf("Value of y = %d\n",y);
 x++;
 printf("\nValue after increment of x = %d\n",x);
 printf("Value after increment of p = %d\n",*p);
 getch();
}
Output:
Value of x = 10
Value of y = 10
Value after increment of x = 11
Value after increment of y = 10 //value of y does not change because no link between them
Value of x = 11
Value of pointer = 11
Value after increment of x = 12
Value after increment of p = 12  //value of pointer get changed because pointer itself make a link
Pointer to Function
When pointers are passed to a function then the address of the data item is passed and thus the function can freely access the contents of that address from within the function. Function is act as a call by reference.
Prototype
Return-type function-name(data-type *);
Definition
return-type function-name(data-type *variable)
{
            -------
            ------
}
How to call function
function-name(&variable);
//swaping of two numbers by pointer with function
#include<stdio.h>
#include<stdio.h>
void swapno(int *,int *);   //Prototype function
void main()
{
 int no1,no2;
 clrscr();
 printf("Enter any two integers\n");
 scanf("%d%d",&no1,&no2);
 printf("Before swaping: no1=%d no2=%d\n",no1,no2);
 swapno(&no1,&no2);   //variable reference is passed to function
 printf("\nAfter swaping: no1=%d no2=%d\n",no1,no2);
 getch();
}
void swapno(int *p1,int *p2)  //whenever this function is called then p1 and p2 points to address of no1 and no2 respectively
{
 int temp;
 temp = *p1;
 *p1 = *p2;
 *p2 = temp;
}
Output:
Enter any two integers
123
345
Before swaping: no1=123 no2=345
After swaping: no1=345 no2=123
Pointer and Array
By using pointer we can also access values from an array. If you declared pointer as int *p and array as int x[3]={1,2,3}; then it is valid to point p=&x; but it means that pointer is pointed to a first location of array. Why it is so? Because pointer has 2 bytes and it is only capable to point to one by one location. So you have to write a loop as follows:
for(p=&x;p<=&X[2];p++)
{
  printf(“%d”,*p);   ---------1
}
you can be use I variable to access index as follows:
p = &x;
for(i=0;i<3;i++)
{
  printf(“%d”,*(p+i)); --------2
}
In 1 and 2 you will get the same output. It is your choice how to access elements of array by pointer.
e.g. int x[5]={12,23,34,45,56},*p;
       p = &x;
       - The first element of array at *p
       - The second element is at *(p+1)
       - The third element of array at *(p+2)
       - The fourth element is at *(p+3)
       - The fifth element of array at *(p+4)
//using pointer with array
#include<stdio.h>
#include<conio.h>
void main()
{
int x[5] = {4,5,6,2,3};
int *p,sum=0;
clrscr();
printf("Regular listing\n");
for(p=&x[0];p<=&x[4];p++)
{
printf("Address = %u , value of pointer = %d\n",p,*p);
sum = sum + *p;  //element of array add to sum
}
printf("Sum = %d \n",sum);
getch();
}
Output:
Regular listing
Address = 65516 , value of pointer = 4
Address = 65518 , value of pointer = 5
Address = 65520 , value of pointer = 6
Address = 65522 , value of pointer = 2
Address = 65524 , value of pointer = 3
Sum = 20
//Sorting of array of n numbers by using two pointers
#include<stdio.h>
#include<conio.h>
void main()
 {
 int x[100],*p1,*p2,temp,n;
 clrscr();
 printf("Enter how many elements\n");
 scanf("%d",&n);
 //to scan values using pointer till n-1
 printf("Enter elements of array for sorting\n");
 for(p1=&x[0];p1<=&x[n-1];p1++)
 {
 scanf("%d",p1); //for scanning only use p1 because it is already pointed to address of x
 }
 //process
  for(p1=&x[0];p1<=&x[n-1];p1++)
  {
   for(p2=p1+1;p2<=&x[n-1];p2++)
            {
             if(*p1 > *p2)  //After comparison swap the values
             {
             temp = *p1;
             *p1 = *p2;
             *p2 = temp;
             }
            }
  }
 printf("Sorted elements of array are\n");
 for(p1=&x[0];p1<=&x[n-1];p1++)
 {
 printf("%d\t",*p1);
 }
 getch();
 }
Output:
Enter how many elements
7
Enter elements of array for sorting
34
76
12
33
98
65
45
Sorted elements of array are
12      33      34      45      65      76      98
Pointer to character array
The pointer to string will lead to a saving in memory.
char *s; - able to accept a long string (single dimensional char array).
char *s[]; - able to accept list of string (multi dimensional char array).
//Prog to find reverse of string by pointer
#include<stdio.h>
#include<conio.h>
void main()
{
 char str[20],rev[20],*s2,*s3;
 int len;
 clrscr();
 printf("Enter any string\n");
 gets(str);
 len=strlen(str);  //library function of string
 //process
 s3=&rev;
 for(s2=&str[len-1];s2>=&str[0];s2--)  //s2 points to last location of str
 {
  *s3 = *s2;  //copy s2 to s3 in reverse order of str
  s3++;
 }
 *s3='\0';  //termination of rev
 printf("Reverse of string = %s\n",rev);
 getch();
}
Output:
Enter any string
phoenix
Reverse of string = xineohp
Dynamic Memory Allocation
Memory allocates at run time according to user specification known as dynamic memory allocation. This type of allocation permits programmer to allocate additional memory space as per programs requirement as well as you can release unwanted memory at the time of execution. In short we can perform well memory management.
Library functions related to dynamic memory allocation
malloc()
Allocates requested size of bytes and returns a pointer to the first byte of the allocated memory.
calloc()
Allocates space for array of elements, initializes them with zero and returns a pointer to the allocated memory.
realloc()
Modifies the size of previously allocated memory.
free()
Releases the previously allocated memory.
 Allocating block of memory using malloc()
 The malloc() function  is used to reserve a block of memory of specified size at run time of a program.
Pointer-variable = (data-type *)malloc(byte-size*user-defined-size);
     
Allocating block of memory using calloc()
 The calloc() function  is used to reserve a block of memory of specified size at run time of a program. It is capable of allocating multiple blocks of memory.
Pointer-variable = (data-type *)calloc(user-defined-size,byte-size);
Allocating block of memory using realloc()
Sometimes it may happen so that the memory you have allocated dynamically might be too large compared to the requirement or too small that is not sufficient to meet requirements. In such case you may alter the memory size by using realloc() function.
Pointer-variable = realloc(pointer-variable, user-sized*sizeof(ptr));
Releasing memory using free()
The memory allocated for the program during compile-time is automatically released by the system. But it is responsibility of the programmer to release the dynamically allocated memory. For this process free() is used.
free(pointer-variable);
//sum of all elements of dynamic array
#include<stdio.h>
#include<conio.h>
void main()
 {
 int *p,sum=0,n,i;   //p1 for dynamic array
 clrscr();
printf(“\nEnter size of array”);
scanf(“%d”,&n);
p = (int *)malloc(sizeof(p)*n); //Allocates n no. of bytes for p
 printf("Enter %d elements of array\n",n);
 for(i=0;i<n;i++)
 {
 scanf("%d",p+i);  //scan elements of p array
 }
 for(i=0;i<n;i++)
 {
  sum = sum + *(p+i);
 }
printf("Elements of array\n",n);
 for(i=0;i<n;i++)
 {
   printf("%d\t",*(p+i));
 }
 free(p);  //After processing free allocated memory block
 printf("\nSum of all elements = %d\n",sum);
 getch();
 }
Output:
Enter size of array: 5
Enter 5 elements of array
1
2
3
4
5
Elements of array
1       2       3       4       5
Sum of all elements = 15
//Program to merge elements of dynamic array
#include<stdio.h>
#include<conio.h>
void main()
{
  int *x,*y,*z,n,m,i,k=0;
  float avg;
  clrscr();
  printf("Enter size of 1st array\n");
  scanf("%d",&n);
 printf("Enter size of 2nd array\n");
  scanf("%d",&m);
  //DMA for x and y array
  x=(int *)malloc(sizeof(x)*n);
  y=(int *)malloc(sizeof(y)*m);
  printf("Enter ele of 1st array\n");
  for(i=0;i<n;i++)
  {
   scanf("%d",(x+i));
  }
   printf("Enter ele of 2nd array\n");
  for(i=0;i<m;i++)
  {
   scanf("%d",(y+i));
  }
  z=(int *)malloc(sizeof(z)*(n+m));  //DMA for z array
  for(i=0;i<n;i++)
  {
   *(z+k)=*(x+i);  //copy elements of x to z
   k++;
  }
   for(i=0;i<m;i++)
  {
   *(z+k)=*(y+i);  //Merge elements of y to z
   k++;
  }
  printf("\n After merging Elements are \n:");
  for(i=0;i<k;i++)
  {
  printf("%d\t",*(z+i));
  }
  free(x);
  free(y);
  free(z);
getch();
}
Output:
Enter size of 1st array
4
Enter size of 2nd array
5
Enter ele of 1st array
1
2
3
4
Enter ele of 2nd array
5
4
3
2
1
After merging Elements are:
1       2       3       4       5       4       3       2       1
//Dynamic matrix
#include<stdio.h>
#include<conio.h>
void main()
{
 int **m;  //pointer variable for dynamic matrix it is also known as pointer to pointer
 int i,j,r,c;
 clrscr();
printf("How many rows and columns\n");
 scanf("%d %d",&r,&c);
  *m = (int *)malloc(sizeof(int) * r);  //Dynamic memory allocation for rows base address
 for(i=0;i<r;i++)
 {
  *(m+i) = (int *) malloc(sizeof(int) *c);    //Dynamic memoty allocation for columns base address
  }
printf(“\nEnter %dx%d elements of dynamic matrix:\n”,r,c);
for(i=0;i<r;i++)
 {
  for(j=0;j<c;j++)
  {
  scanf("%d",&m[i][j]);    //scan elements of matrix
   }
 }
printf(“\nElements of dynamic matrix:\n”);
for(i=0;i<r;i++)
 {
  for(j=0;j<c;j++)
  {
  printf("%d\t",m[i][j]);
   }
 printf("\n");
 }
 getch();
}
Output:
How many rows and columns
3
3
Enter 3x3 elements of dynamic matrix:
12
23
34
45
56
67
78
89
98
Elements of dynamic matrix:
12      23      34
45      56      67
78      89      98
In following program arrow operator(->) is used. This operator is useful while accessing data members of structure through pointer variable. This operator is also known as direct member selector.
Whenever it is used then one problem occurred that is this operator used with pointer variable and if you increment the pointer then its base address get changed. So to avoid it you have to declared another pointer variable to copy base address for further programming.
Syntax: pointervariable->data member;
//program to create dynamic structure
#include<stdio.h>
#include<conio.h>
void main()
{
  struct book
   {
    int bno;
    char bname[10];
    int price;
   };
   struct book *b,*temp;
   int n,i;
   printf("How many books \n");
   scanf("%d",&n);
   // dma
   b = (struct book *) malloc(sizeof(b) * n);  //Dynamic memory allocation for structure
   clrscr();
   temp=b; //copy base add of b into temp
   printf("Enter %d details of books\n",n);
   for(i=0;i<n;i++)
   {
   Printf(“Enter book no., name and price respectively\n”);
   scanf("%d %s %d",&b->bno,&b->bname,&b->price);
   b++;
   }
   b=temp; //recall base add. of b for displaying records
   printf("Details of books are\n");
   printf("Bookno \t Bookname \t Price\n");
   printf("====================================\n");
   for(i=0;i<n;i++)
   {
   printf("%3d \t %-10s \t %4d\n",b->bno,b->bname,b->price);
   b++;
   }
getch();
}
Output:
Enter 3 details of books
Enter book no., name and price respectively
101
Java
400
Enter book no., name and price respectively
102
C#
550
Enter book no., name and price respectively
103
VB6
200
Details of books are
Bookno   Bookname        Price
====================================
101      Java             400
102      C#               550
103      VB6              200

No comments:

Post a Comment