Tuesday, 3 March 2015

The void pointer (void*) in Cpp with examples

The void pointer (void*) in Cpp with examples

The void pointer is also a pointer that points to anything which not known at the declaration time. Or in other words a void* pointer is a pointer that point to a value that has no type. A void pointer seems to be of limited use. However, when combined with the ability to cast such a pointer to another type, they are quite useful.

The void* has an  undetermined length and undetermined dereference properties, void pointer can point to any data type, from an integer value or a float to a string of characters. That's why it is also referred to as a generic pointer.

For example a function that’s returning value is void* means that can be doing the below operations

Case1: Unformatted memory: This is what operator new and malloc return: a pointer to a block of memory of a certain size. Since the memory does not have a type

Case2: It is an opaque handle: it references a created object without naming a specific type. Code that does this is generally poorly formed, since this is better done by forward declaring a struct/class and simply not providing a public definition for it. Because then, at least it has a real type.


Small example using the swap function:
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
using namespace std;
void swap (int *pVal1, int *pVal2)
{
 int temp;
 temp = *pVal1;
 *pVal1 = *pVal2;
 *pVal2 = temp;
}
int main ()
{
  int iVal1 = 10, iVal2 = 20;
 cout << "iVal1 = " << iVal1 << " iVal2 = " << iVal2 << endl;
 swap (&iVal1, &iVal2);
 cout << "iVal1 = " << iVal1 << " iVal2 = " << iVal2 << endl;
  getchar ();
  return 0;
}
The output of the above program is:
iVal1 = 10 iVal2 = 20

iVal1 = 20 iVal2 = 10

The above swap function is used to understand the working of the pointers. Using the above code we can understand that the code is copying bit pattern and it does not care much about the type. It's not that tough for us to make the code type independent if we use void*.

We have to type cast the void pointer to some other pointer that we are expecting before dereferencing it.

However, on the other hand, void pointers have a great limitation such as the data pointed by them cannot be directly dereferenced since there is no type information to guide the compiler in interpreting the underlying bit pattern. So, we will always have to cast the address in the void pointer to some other pointer type that points to a concrete data type before dereferencing it.

The declaration of the void pointer is

void *pcPtr;

Here is a simple example using the void* pointer.
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
using namespace std;
enum ENMType  { 
   enmINT = 0, 
   enmFLOAT, 
   enmSTRING, 
 }; 
void GetPrint (void *pcPtr, ENMType enmType) 
{   
  switch (enmType) 
   { 
 case enmINT: 
   cout << *(int*) pcPtr << endl; 
  break; 
 case enmFLOAT: 
  cout << *(float*) pcPtr << endl; 
  break; 
 case enmSTRING: 
  cout << (char*) pcPtr << endl; 
  break; 
   } 
}   
int main () 
{ 
   int iIntVal = 112; 
   float fFloatVal = 500.890; 
   char *pcCharVal = "Small exaple that is to verify the void*"; 
   GetPrint (&iIntVal, enmINT); 
   GetPrint (&fFloatVal, enmFLOAT); 
   GetPrint (pcCharVal, enmSTRING); 
   getchar ();
   return 0; 
}

The Output of the above program is:
112

500.89

Small exaple that is to verify the void*

In the code above, the function GetPrint () is called with an argument of &iIntVal, &fFloatVal, and pcCharVal which are pointers. Then it gets them as void * pcPtr which is a void* pointer type.

Inside the GetPrint () function, it prints out after casting them to appropriate types and dereferencing them.

Let us see the another example that explains automatic conversion of the void*
#include <iostream> 
int main () 
{ 
    int iVal = 0,*piVal = NULL;
   char *pcChVal = NULL;
   void *pPtrVoid = NULL;
   pPtrVoid = piVal;
   pPtrVoid = pcChVal;
   const int *pciVal = &iVal;
   pPtrVoid = pciVal;
   getchar ();
   return 0; 
}


If we compile it, we get an error:
 error C2440: '=' : cannot convert from 'const int *' to 'void *'

To resolve this problem
We have to cast the const int pointer to const void pointer
   const void *pPtrVoid1 = pciVal;  

   pPtrVoid1 = const_cast<int *>(pciVal); 


 The below are the thumb rules that we have to remember:
We can't declare a variable as a void type:
void ovTemp 

We're not allowed deference void pointer
void temp = *pcVoidptr1;

It does not have any data type associated with it
It can store address of any type of variable
A void pointer is a C convention for a raw address.
The compiler has no idea what type of object a void Pointer really points to ?

Let us see the full-fledged final code for swap function using void*:
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
void SwapWithVoidPointer (void *vPtr1, void *vPtr2, const int iCSize)
{
 char *pcchBuffer = (char *)malloc (sizeof(char) * iCSize);
 memcpy (pcchBuffer, vPtr1, iCSize);
 memcpy (vPtr1, vPtr2, iCSize);
 memcpy (vPtr2, pcchBuffer, iCSize);
 free (pcchBuffer); pcchBuffer = NULL;
}
int main ()
{
 int iVal = 50, iVal1 = 80;
 cout << iVal << " , " << iVal1 << endl;
 SwapWithVoidPointer(&iVal, &iVal1, sizeof (int));
 cout << iVal << " , " << iVal1 << endl;
 cout << endl;
 char *pchDuck = _strdup ("QUACK");
 char *pchHyenas = _strdup ("LAUGH");
 cout << pchDuck << " , " << pchHyenas << endl;
  SwapWithVoidPointer (&pchDuck, &pchHyenas, sizeof (char **));
 cout << pchDuck << " , " << pchHyenas << endl;
  getchar ();
  return 0; 
}

Output is:
50 , 80

80 , 50

QUACK , LAUGH

LAUGH , QUACK


We can find other usages of void * in memory functions:
 void * memcpy ( void * destination, const void * source, size_t sz)

• void *memmove(void *dest, const void *src, size_t sz)

• void * memset ( void * destination, int source, size_t sz )

• int memcmp (const void *s1, const void *s2, size_t sz )

 


No comments: