Dynamic memory allocation


Though arrays can be used for data storage, they are of fixed size. The programmer must know the size of the array while writing the program. In most situations, it is not possible to know the size of the memory required until run time. At execution time, a program can request more memory from a free memory pool (heap). Dynamic memory allocation refers to the allocation of such memory during program execution. The only way to access this dynamically allocated memory is through pointers.

What are the differences between dynamic memory allocation and static memory allocation?

Static memory allocation
Dynamic memory allocation
It is the process of allocating memory at compile time.
It is the process of allocating memory during execution of program.
Fixed number of bytes will be allocated.
Memory is allocated as and when it is needed.
The memory is allocated in memory stack.
The memory is allocated from free memory pool (heap).


* The limit for dynamic memory allocation can be as large as the amount of available physical memory in the computer or the amount of available virtual memory in a virtual memory system.


C supports many built-in standard library functions for efficient dynamic memory allocation / de-allocation. Their prototypes are declared in the header files stdlib.h, alloc.h and malloc.h. These functions are: malloc(), calloc(), realloc() and free().

1) malloc() — allocates a block of memory

The function malloc() has the following prototype:

void *malloc(size_t size); 

The function malloc() allocates a block of size bytes from the free memory pool (heap). It allows a program to allocate an exact amount of memory explicitly, as and when needed.
Argument: The parameter passed to malloc() is of the type size_t. This type is declared in the header file stddef.h. size_t is equivalent to the unsigned int data type. Thus, in compilers where an int is 16 bits in size, malloc() can allocate a maximum of 64KB at a time, since the maximum value of an unsigned int is 65535.

Return value:
  • On success, i.e., if free memory is available, malloc() returns a pointer to the newly allocated memory. Usually, it is generic pointer. Hence, it should be typecast to appropriate data type before using it to access the memory allocate.
  • On failure, i.e., if enough free memory does not exist for block, malloc() returns NULL. The constant NULL is defined in stdio.h to have a value zero. Hence, it is safe to check the return value.

Ex: 1) malloc(30); allocates 30 bytes of memory and returns the address of byte0.
      2) malloc(sizeof(float)); allocates 4 bytes of memory and returns the address of byte0.

What do malloc(-20) and malloc(0) return?

The parameter to malloc() function should be an unsigned integer. If we pass any negative value as an argument, then NULL is returned. So, malloc(-20) returns NULL.

Though the value 0 is not a negative integer, malloc(0) does not return pointer to 0 bytes or NULL pointer. Instead, it also returns the constant NULL.


2) calloc() — allocates multiple blocks of memory
The function malloc() has the following prototype:

void *calloc(size_t nitems,size_t size);

calloc() provides access to the C memory heap, which is available for dynamic allocation of variable-sized blocks of memory.
Arguments: Unlike malloc(), the function calloc() accepts two arguments: nitems and size. The parameter nitems specifies the number of items to allocate and size specifies the size of each item.
Return value:
ü  On success, i.e., if free memory is available, calloc() returns a pointer to the newly allocated memory. Usually, it is generic pointer. Hence, it should be typecast to appropriate data type before using it to access the memory allocated.
ü  On failure, i.e., if enough free memory does not exist for block, calloc() returns NULL. The constant NULL is defined in stdio.h to have a value zero. Hence, it is safe to verify the return value before using it.

Ex: 1) calloc(3,5); allocates 15 bytes of memory and returns the address of byte0.
      2) malloc(6,sizeof(float)); allocates 24 bytes of memory and returns the address of byte0.



3) realloc() — grows or shrinks allocated memory
The function malloc() has the following prototype:

                                             void *realloc(void *block,size_t size);

The function realloc() adjusts the amount of memory allocated to the block to size, copying the contents to a new location if necessary.
Arguments: block is the pointer to the memory block that is previously obtained by calling malloc(), calloc() or realloc(). If block is NULL pointer, realloc() works just like malloc().
Size is the new size for allocated block.
Return value:
  • On success, this function returns the address of the reallocated block, which might be different from the address of the original block.
  • On failure, i.e., if the block can’t be reallocated or if the size passed is 0, the function returns NULL.

The function realloc() is more useful when the maximum size of allocated block can not be decided in advance.
Ex:     int *a;
          a=(int *) malloc(30); //first 30 bytes of memory is allocated.

Why does not sizeof operator tell us the size of block of memory pointed by a pointer?
The sizeof operator does not know the at malloc() has been used to allocate pointer; sizeof tells us the size of the pointer itself. There is no portable way to find out the size of a block allocated by malloc().
          a=(int *) realloc(a,15); //later the allocated memory is shrink to 15 bytes.


4) free() — de-allocates memory
The function free() has the following prototype:

                                                              void free(void *block);

The function free() de-allocates a memory block pointed by block.  
Argument: block is the pointer that is points to allocated memory by malloc(), calloc() or realloc(). Passing an uninitialized pointer, or a pointer to a variable not allocated by malloc(), calloc() or realloc() could be dangerous and disastrous.
Ex:     int *a;
          a=(int *) malloc(30); //first 30 bytes of memory is allocated.
          free(a); //de-allocates 30 bytes of memory.

How does free() know how many bytes to free?
The malloc() / free() implementation remembers the size of each block allocated and returned. So, it is not necessary to remind it of the size when freeing.

Pointers and One-Dimensional numeric arrays
An array is homogeneous collection of elements stored in contiguous memory locations referred by common name. The array name itself is the base address, i.e., the address of first element in array. As we know that the pointer is an address, the array name itself is a pointer.

Accessing array elements through a pointer
Usually, each element in an array is accessed through an index that starts from 0 and ends with n-1 where n is the size of array. e.g., a[0] is the first element, a[1] is second element and so on…
Similarly, by using a pointer variable, all the elements are accessed as follows:
1.    First declare a pointer variable. The type of pointer variable should be same as the type of array.
2.    Initialize the pointer variable with the base address of array.
3.    Access each element by placing an * before incremented pointer or before the expression of the form (ptr+i) where ptr is the pointer variable and i is the index value.
The following program demonstrates this:

Write a program to add elements of array using a pointer

#include$ < $stdio.h$ > $
void display(int *,int);
void sum(int *,int);
main()
{
          int  a[10],n,i,*ptr; //step-1: Declaration of a pointer variable
          printf(“\n Enter the array size:”);
          scanf(“%d”,&n);
          printf(“\nEnter the array elements:”);
          for(i=0;i
          scanf(“%d”,&a[i]);
          ptr=&a[0];  //step-2: Initalization of pointer variable
          display(a,n); //the name of the array itself is the base address
          sum(ptr,n);
}
void display(int a[ ],int n)
{
          int i;
          printf(“\n The array elements are:”);
          for(i=0;i
          printf(“%d\t”,a[i]);
}
void sum(int *ptr,int n)
{
          int i,total;
          total=0;
          //step-3: Accessing array elements through pointer
          for(i=0;i
          total=total+*ptr++;  //or total=total+*(ptr+i);
          printf(“\n The sum of array elements=%d”,total);
}
Output:
Enter the array size:5
Enter the array elements: 2  4  6 3 1
The array elements are: 2   4        6        3        1
The sum of array elements=16

Note:
a[i] is equivalent to i[a] or *(a+i) or *(i+a)


 Dynamically allocated 1-D array

When we declare an array, we declare it as an array of fixed size. It can’t be grown or shrink as and when needed. To overcome this problem, dynamically allocated array is introduced. To work with dynamically allocated array, do the following:
  1. Declare a pointer variable.
  2. Allocate memory to that pointer variable.
  3. Initialize and access array elements through pointer variable.
  4. De-allocate the pointer variable.
The following program demonstrates this concept:

Write a program to sort elements of array using pointers.

#include$ < $stdio.h$ > $
void display(int *,int);
void sort(int *,int);
main()
{
          int  *a,n,i; //step-1: Declaration of a pointer variable
          printf(“\n Enter the array size:”);
          scanf(“%d”,&n);
          a=(int *) malloc(n*sizeof(int));   //step2: Allocate memory
          printf(“\nEnter the array elements:”);
          for(i=0;i
          scanf(“%d”,a+i);
          display(a,n); 
sort(a,n);
          free(a);  //step-4: de-allocating memory
}
void display(int a[ ],int n)
{
          int i;
          printf(“\n The array elements are:”);
          for(i=0;i
          printf(“%d\t”,a[i]); //step-3: accessing elements
}
void sort(int *ptr,int n)
{
          int i,j,temp;
          for(i=0;i
          {
                   for(j=i+1;j
                   {
                             if(*(ptr+i)>*(ptr+j))    //step-3: accessing elements
                             {
                                      temp=*(ptr+i);
                                      *(ptr+i)=*(ptr+j);
                                      *(ptr+j)=temp;
                             }
                   }
          }
          printf(“\n After sorting:”);
          display(ptr,n);
}


Note:
 a[i] is equivalent to i[a] or *(a+i) or *(i+a)

Can we use the content of allocated memory after freeing it?
Some early documentation for malloc() stated that the contents of freed memory were “left undisturbed”. So, few programmers would use the contents of freed memory deliberately.

Function returning 1-D array
By using pointers, a function can return more than one value at a time. As array contains more than one element and array name is the base address, we can return the base address. This gives us a view that a function can return more than one value at a time. The following program demonstrates this concept:

Write a program to demonstrate a function that returns a sorted array.
#include$ < $stdio.h$ > $
int * sort(int a[ ],int); //function prototype
main()
{
        int *p;
        int a[10],n,i;
        printf("\n Enter the array size:");
        scanf("%d",&n);
        printf("\n Enter the array elements:");
        for(i=0;i
        scanf("%d",&a[i]);
        printf("\n Before sorting:");
        for(i=0;i
        printf("%d\t",a[i]);
        p=sort(a,n); //function call- p holds the base address of returned array
        printf("\n After sorting:");
        for(i=0;i
        printf("%d\t",*p++);
}
int *sort(int a[ ],int n)
{
        int i,j,temp;
        for(i=0;i
        {
                for(j=i+1;j
                {
                        if(a[i]>a[j])
                        {
                                temp=a[i];
                                a[i]=a[j];
                                a[j]=temp;
                        }
                }
        }
        return a;  //sends the base address of sorted array
}
Output:
Enter the array size: 5
Enter the array elements:35
3
46
43
1
Before sorting: 35    3        46      43      1
After sorting: 1        3        35      43      4

 Pointers and Two-Dimensional numeric arrays

The two-dimensional array is an array with two subscripts. As same with one-dimensional numeric array, the name of two-dimensional array is also a base address. i.e., it is the address of element that is present in first row and first column (address of a[0][0]).

 Pointer-to-2-D array

The way we can have a pointer to an integer, or a pointer to a float, can we also have a pointer to an array? The answer is YES. A two-dimensional array can be accessed through a pointer as follows:
  1. First, declare a pointer to array. This declaration of pointer-to- 2-D array is little clumsy. It has the following form:
                                             $ < $data type$ > $ (*$ < $ptr_name$ > $)[size];

Ex: int (*q)[4];
This declaration gives a meaning that q is a pointer-to-2-D array of 4 columns.
Once a pointer is declared, it should be initialized with the name of 2-D array that
2.    declared and initialized earlier.
e.g., ptr=a;   where a is two-dimensional array.
  1. Now, each element gets accessed with the help of the following expression:
*(*(ptr+i)+j) where i is the index of row and j is the index of column.


Write a program to access a 2-D array using pointer and print it in matrix form
#include$ < $stdio.h$ > $
main()
{
          int a[10][10],m,n,i,j;
          int (*ptr)[10]; //pointer-to-array
          printf(“\n Enter the matrix row and column values:”);
          scanf(“%d%d”,&m,&n);
          printf(“\n Enter matrix elements:”);
          for(i=0;i
          for(j=0;j
          scanf(“%d”,&a[i][j]);
          ptr=a;
          printf(“\n The matrix elements:\n”);
          for(i=0;i
          {
                   for(j=0;j
                   {
                             printf(“%d\t”,*(*(ptr+i)+j));
                             printf(“\n”);  
                   }
          }
         
}
Output:
Enter matrix row and column values: 2 2
Enter matrix elements: 23 45 65 232
The matrix elements:
23           45
65      232


Dynamically allocated 2-D array
When we declare an array, we declare it as an array of fixed size. It can’t be grown or shrink as and when needed. To overcome this problem, dynamically allocated array is introduced. To work with dynamically allocated array, do the following:
  1. Declare a pointer variable.
  2. Allocate memory to that pointer variable.
  3. Initialize and access array elements through pointer variable.
  4. De-allocate the pointer variable.
The following program demonstrates this concept:

/*A program to multiply two matrices using pointers*/
#include$ < $stdio.h$ > $
void display(int **,int,int);
void multiply(int **,int **,int,int,int,int);
main()
{
          int **a,**b,m,n,p,q,i,j;  //step-1
       
printf("\n Enter the first matrix order:");
          scanf("%d%d",&m,&n);
          printf(“\n Enter second matrix order:”);
          scanf(“%d%d”,&p,&q);
          if(n!=p)
                   printf(“\n Sorry, matrix multiplication is not possible”);
          else

          {
                   a=(int **)malloc(m*sizeof(int));
                   for(i=0;i
                   a[i]=(int *)malloc(n*sizeof(int));
                   printf("\n Enter first matrix elements");
                   for(i=0;i
                   for(j=0;j
                   scanf("%d",&a[i][j]);
                   printf(“\n First matrix\n”);
                   display(a,m,n);
                  
                   b=(int **)malloc(p*sizeof(int));
                   for(i=0;i
                   a[i]=(int *)malloc(q*sizeof(int));
                   printf("\n Enter second matrix elements");
                   for(i=0;i
                   for(j=0;j
                   scanf("%d",&b[i][j]);
                   printf(“\n Second matrix\n”);
                   display(b,p,q);
                  
                   multiply(a,b,m,n,p,q);
                   free(a);
                   free(b);
          }
}
void display(int **a,int m,int n)
{
          nt i,j;
          for(i=0;i
          {
                   for(j=0;j
                   printf("%d\t",a[i][j]);
                    printf(“\n”);
}
}
void multiply(int **a,int **b,int m,int n,int p,int q)
{
          int **c,i,j;
          c=(int **)malloc(m*sizeof(int));
          for(i=0;i
          c[i]=(int *)malloc(q*sizeof(int));

          for(i=0;i
          {
                   for(j=0;j
                   {
                             c[i][j]=0;
                             for(k=0;k
                             c[i][j]=c[i][j]+a[i][k]*b[k][j];
                   }
                   printf(“\n The resultant matrix:\n”);
          display(c,m,q);
          free(c);
}

(Click next to read rest of the article)


Array of pointers

There is an array of ints or an array of floats. Similarly, there can also be an array of pointers. Since, a pointer is an address; an array of pointers is nothing but a collection of addresses. The addresses present in the array of pointers can be addresses of isolated variables or addresses of array elements or any other addresses. All rules that apply to an ordinary array apply to the array of pointers as well. The following program demonstrates the concept of array of pointers:

Write a program to demonstrate array of pointers.

#include$ < $stdio.h$ > $
main()
{
          int *a[4];   //declaration of array of pointers
          int i=32,j=45,k=2,l=35,m;
          a[0]=&i;
          a[1]=&j;
          a[2]=&k;
          a[3]=&l;
          for(m=0;m<3 data-blogger-escaped-m="m" data-blogger-escaped-o:p="o:p">
          printf(“%d\t”,*(a[m])); //accessing the content in each element that is a pointer
}
Output: 32       45        2          35


Write a program to print transpose a matrix using array of pointers.
#include$ < $stdio.h$ > $
main()
{
        int *a[10];
        int m,n,i,j;

        printf("\n Enter matrix order");
        scanf("%d%d",&m,&n);

        for(i=0;i
        a[i]=(int *)malloc(n*sizeof(int));

        printf("\n Enter matrix elements:");
        for(i=0;i
        for(j=0;j
        scanf("%d",&a[i][j]);

        printf("\n The original matrix\n");
        for(i=0;i
        {
                for(j=0;j
                printf("%d\t",a[j][i]);
                printf("\n");
        }

        printf("\n The transpose of matrix\n");
        for(i=0;i
        {
                for(j=0;j
                printf("%d\t",a[j][i]);
                printf("\n");
        }
}
Output:
Enter matrix order: 2   3
Enter matrix elements: 1 2 3 4 5 6
The original matrix
1        2        3
4        5        6
The transpose of matrix
1                    4
2                    5
3                    6            

Write a program to print transpose of a matrix using pointer-to-array

#include$ < $stdio.h$ > $
main()
{
          int a[10][10],m,n,i,j;
          int (*ptr)[10]; //pointer-to-array
          printf(“\n Enter the matrix row and column values:”);
          scanf(“%d%d”,&m,&n);
          printf(“\n Enter matrix elements:”);
          for(i=0;i
          for(j=0;j
          scanf(“%d”,&a[i][j]);
          ptr=a;
          printf(“\n The matrix elements:\n”);
          for(i=0;i
          {        for(j=0;j
                   {
                             printf(“%d\t”,*(*(ptr+i)+j));
                             printf(“\n”);  
                   }
          }
          printf(“\n The transpose of matrix:\n”);
          for(i=0;i
          {        for(j=0;j
                   {
                             printf(“%d\t”,*(*(ptr+j)+i));
                             printf(“\n”);  
                   }
          }
}
          
Output:
Enter matrix row and column values: 2 2
Enter matrix elements: 23 45 65 232
The matrix elements:
24           45
65          232
The transpose of matrix:
24        65
45       232

Compare array of pointers to pointer-to-array?

1) A pointer to an array is a variable that contains the address of (points to) a multi-dimension variable that could contain anything (multiple strings or multiple longs etc.).
An array of pointers is a single-dimensional variable that holds multiple addresses (pointers) each of which could point to anything (other variables, objects etc.).

2) The number in subscript of pointer-to-array denotes the number of columns.
    The number in subscript of array of pointers denotes the number of rows.

 Pointers and Strings

As a group of integers is stored in an integer array, a group of characters will be stored in a character array. This character array is called as a string. Usually, a string constant is a one-dimensional array of characters terminated by a null character (\0).

 Accessing a string by using a pointer

Because a string is one-dimensional array of characters and the array name is the base address, the name of the character array also becomes the base address. In order to access string with the help of pointer, do the following:
  1. First declare a pointer of type char.
e.g., char *ptr; //A character pointer
  1. Initialize the pointer with the name of character array that was declared and initialized earlier.
e.g., char s[]=”Ravi Chandra”;
          ptr=s; //holds the base address of character array ‘s’
  1. Access each character of string with the help of pointer by incrementing once till the \0 character is encountered.
e.g.,   while(*ptr!=’\0’)
          {
                   printf(“%c”,*ptr);
                   ptr++;
          }

Write a program to read a string and print a string along with its length

#include$ < $stdio.h$ > $
int stringlength(char *);
main()
{
          char s[ ]=”Ravi Chandra”;
          char *ptr;
          int len;
          cptr=s;
           len=stringlength(s);
          printf(“\n The length of string=%d”,len);
}
int stringlength(char *s)
{
          int count=0;
          printf(“\n Given string is=”);
          while(*s!=’\0’)
          {
                   printf(“%c”,*s);
                   count++;
                   s++;
          }
          return count;
}
         
Output:
Given string is= Ravi Chandra
The length of string=12      

Write a program to count number of alphabets, digits, spaces and special characters in a line of text

#include$ < $stdio.h$ > $
main()
{
          char  line[100];
          char *ptr;
          int nalpha,ndigit,nspace,nspecial;
          printf(“\n Enter a line of text:”);
          scanf(“%[  ^\n]”,line);
          ptr=line;
          nalpha=nspace=ndigit=nspecial=0;
          while(*ptr!=’\0’)
          {
                   if(toupper(*ptr)>=’A’ && toupper(*ptr)<=’Z’)
                   nalpha++;
                   else if(*ptr>=’0’&&*ptr<=’z’)
                   ndigit++;
                   else  if(*ptr= =’ ‘ || *ptr= =’\t’)
                   nspace++;
                   else
                   nspecial++;
          }
          printf(“\n No.of alphabets=%d”,nalpha);
          printf(“\n No.of digits=%d”,ndigits);
          printf(“\n No.of spaces=%d”,nspace);
printf(“\n No.of special characters=%d”,nspecial);
}
Output:
Enter a line of text: Master says, “B.Tech 1st  year students are brilliant”
No.of alphabets=41
No.of digits=1
No.of spaces=5
No.of special symbols=4

Pointer to a string

Suppose we wish to store the string “Hello friend”. We may either store it in a character array or we may ask the C compiler to store it some where in memory and assign the address of that string in a char pointer. This is shown below:
          char message[ ]=”Hello friend”;
          char *p=”Hello friend”;
However, there are differences between these two:

  1. The size of character array will be more than the size of the character pointer.
Ex:     #include$ < $stdio.h$ > $
          main()
          {
                   char message[]=”Hello friend”;
                   char *p=”Hello friend”;
                   printf(“\n Size of character array=%d”,sizeof(message));
                   printf(“\n Size of character pointer=%d”,sizeof(p));
          }
         
Output (on 32-bit machine):
 Size of character array=13
                     Size of character pointer=4        

  1. A char pointer can be assigned to another char pointer; but a character array can’t be assigned to another character array.
Ex:     #include$ < $stdio.h$ > $
          main()
          {
                   char message[ ]=”Hello friend”;
                   char mesg2[20];
                   char *p=”Hello friend”;
                   char *q;
                  
                   mesg2=message;   //A blunder
                   q=p;    //works
          }

  1. Once a string has been defined using character array, it can’t be initialized to another set of characters. Unlike character array, such an operation is perfectly valid with char pointer.
Ex:     #include$ < $stdio.h$ > $
main()
{
                   char message[]=”Bye Forever”;
                   char *p=”Bye forever”;
                   message=”welcome friend”; // A blunder
                   p=”Welcome friend”;
          }

 Array of pointers to strings

As an array of integer pointers is used to represent a two-dimensional array of integers, array of character pointers is used to hold multiple strings. To deal with multiple strings with the help of array of character pointers, do the following:

  1. First, declare an array of character pointers.
e.g., char *a[10];
          This declaration is used to define a 10-element array of pointers. Thus, a[0] points to first string, a[1] points to second string and so on.

  1. It is not necessary to include a maximum string size within declaration. However, it is necessary to allocate maximum string size as follows:
for(i=0;i
a[i]=(char *) malloc(15*sizeof(char));   //15 is each string’s maximum length

  1. After memory is allocated, the array of character pointers can be initialized and accessed as normal arrays.

The following program demonstrates this concept:

Why can’t I get strcat() to work? I tried

            char *s1=”Hello”;
      char *s2=”World”;
      strcat(s1,s2);
      printf(“%s”,s1);

The main problem here is that the space for the concatenated result is not properly allocated. C compilers allocate memory only for specified objects explicitly mentioned in the source code. The programmer must arrange for sufficient space for the results of run-time operations, such as string concatenation, typically by declaring arrays or by calling malloc().
          The strcat() function performs no allocation. Since, there is no space for concatenated result in first string (or destination string), the strcat() function returns run-time error.

Write a program to sort names using array of character pointers.

#include$ < $stdio.h$ > $
main()
{
          int n,i,j;
          char *names[10],*temp;
         
printf(“\n Enter how many strings:”);
          scanf(“%d”,&n);
         
for(i=0;i
          names[i]=(char *) malloc(15*sizeof(char));
         
          printf(“\n Enter %d names:”,n);
          for(i=0;i
          scanf(“%s”,names[i]);
         
          for(i=0;i
          {        for(j=i+1;j
                   {        if(strcmp(names[i],names[j])>0)
                             {
                                      temp=names[i];
                                      names[i]=names[j];
                                      names[j]=temp;
                             }
                   }
          }
          printf(“\n Names in alphabetical order:”);
          for(i=0;i
          printf(“%s\t”,names[i]);
}
Output:
Enter how many strings: 5
Enter 5 names:
Master
Minister
Servant
King
Queen
Names in alphabetical order: King             Master           Minister         Queen           Servant        


Compare arrays and pointers? 

n   1)   An Arrray is a homogeneous collection of elements stored in contiguous memory locations referred by a common name.A pointer is a special type of variable that holds address as a data item in it. The address is may be of a variable, or of a constant, or of an array, or of a   function, or of another pointer.
2)   An array can hold a collection of pointers.  
       A pointer can hold the base address of an array that is collection of elements.
3)    An array can’t be assigned to another array (even of same type) directly.
       A pointer can be assigned to another pointer (of same type only) directly.
4)    A pointer can be incremented.
        An array name (though it is an address of first element) can not be incremented.
5)    The size of array is fixed. It can never be changed.
        memory allotted to a pointer can be reallocated.
      

 Pointers and const

As we know that const is the keyword that is used to define a symbolic constant that never be changed throughout the program. E.g., the following is the constant definition:
          const float PI=3.1412;
This definition defines a constant PI and this value never be changed through out the program.
 Pointer to constant
When we want to deal with a pointer to constant, do the following:
1)    Declare a pointer to constant that has the following form:

const  $ < $data type$ > $ *  $ < $ptr_name$ > $;

E.g., const int *p;
     The above statement declares p as a pointer to constant integer.
2)    Once a pointer is declared, initialize it with the address of a const value or const array.
E.g., const int a=23;
        p=a; //initialization of pointer with base address of array of constants
3)    Access the const value or const array with the help of pointer.
It is important to note that the value that is being pointed can never be changed. But the pointer that points to constant can be changed. In other words, it can be incremented or decremented.

E.g., The following program demonstrates this concept:

#include$ < $stdio.h$ > $

main()
{
          const int *ptr1,*ptr2;
          const int i=20;
          const int a[ ]={10,20,40,23};
          ptr1=&i;
          ptr2=a;
          printf(“%d”,*ptr1);  //prints the value of i
          i=30;    //a blunder—trying to change the content of const
          printf(“%d”,*ptr1);
          ptr2++;  //valid—a pointer to const can be changed
          printf(“%d”,*ptr2);   // prints the value of a[1]
}
Note: These types of pointers are very useful in char pointers, when pointers are to be passed to a function for printing. Suppose, we are writing a function that is aimed to print a character string, it is good practice to code that function as follows:

void printstring(const char *str)
{
            printf(“%s”,str);
}

The above function accepts a pointer of type const char *(pointer to constant character). The string that is being pointed can never be changed. This is safety measure, since it prevents the accidental modification of the string that is being passed to called function.

Pointer-to-constant means that the value is not changed through that pointer, not which is unchanged through any pointer.
 
 


Constant pointer
When we want to deal with a constant pointer, do the following:
1) Declare a constant pointer that has the following form:

$ < $data type$ > $ *  const  $ < $ptr_name$ > $=$ < $address$ > $;

E.g.,        int a=20;
int * const p=&a;
     The above statement declares p as a constant pointer that holds the address of a.
2) Access the constant pointer to print the original content of variable or array whose address is stored.
          E.g., printf(“%d”,*p); //prints the value of a
It is important to note that the value that is being pointed can be changed. In the above example, the value of a can be changed. But the value of constant pointer can never be changed. i.e., in the above example, p++ or ++p is invalid.

Note: const int * const p=&a;
The above declaration disallows the modification of both p and a. i.e., both pointee and pointer.

What is the difference between const char *p and char* const q?

1)    p is a pointer-to-constant char.
P will be changed. But *p will never be changed.

2)    q is a constant pointer.
q will never be changed. But *q will be changed.