Wednesday, July 29, 2015

void* universal pointer

void* also known as universal pointer or generic pointer can be used to hold the address of any type assigned to it.

void* universal pointer can also be used as a function argument.

Below example transferValues function declares two void* arguments.

Instead of writing two different functions for int and double types only one transferValues function with void* arguments can be used.

void* seems to be usable but there are type-safety related problems with void pointer.

With a suitable casting operation existing void* universal pointer can be converted to an appropriate type.

Because a void pointer can not be dereferenced directly, static_cast can be used to cast from void* to another type.

Following error message is generated by the compiler if a void* is dereferenced before casting to an appropriate type.

'void*' is not a pointer-to-object type
           

Example void pointer project compiled with : g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2


#include <iostream>
using namespace std;

enum ParamType
{
    intType,
    doubleType
};

void transferValues( void* from, void* to, int size, ParamType pType)
{

    if( pType == intType )
    {
         for (int i= 0; i<size; i++)
         {
             static_cast<int*>(to)[i] = static_cast<int*>(from)[i];
         }
    }
    else if( pType == doubleType )
    {
         for (int i= 0; i<size; i++)
         {
             static_cast<double*>(to)[i] = static_cast<double*>(from)[i];
         }
    }
}

int main()
{

    int val = 5;
    void* vPtr = &val;
    // below line generates compile error
    // cout << *vPtr;
    int* newVal = static_cast<int*>(vPtr);
    cout << *newVal << endl;

    double dVal = 5.2;
    vPtr = &dVal;
    double* newDVal = static_cast<double*>(vPtr);
    cout << *newDVal << endl;

    char cVal = 'c';
    vPtr = &cVal;
    char* newCVal = static_cast<char*>(vPtr);
    cout << *newCVal;

    cout << endl << endl;

    int a[5] = { 1, 2, 1, 1, 1 };
    int b[5];

    cout << "Elements of array a = ";
    for( int i = 0; i<5; i++ )
        cout << a[i] << " ";

    cout << endl << "Elements of array b before casting = ";
    for( int i = 0; i<5; i++ )
        cout << b[i] << " ";

    transferValues( a, b, 5, intType );
    cout << endl << "Elements of array b after casting = ";
    for( int i = 0; i<5; i++ )
        cout <<  b[i] << " ";

    double c[5] = { 2.3, 3.3, 4.3, 5.3, 6.3 };
    double d[5];

    cout << endl << endl << "Elements of array c = ";
    for( int i = 0; i<5; i++ )
        cout << c[i] << " ";

    cout << endl <<"Elements of array d before casting = ";
    for( int i = 0; i<5; i++ )
        cout << d[i] << " ";

    transferValues( c, d, 5, doubleType );
    cout << endl << "Elements of array d after casting = ";
    for( int i = 0; i<5; i++ )
        cout << d[i] << " ";

    cout << endl << endl;

    return 0;
}

After running the program following terminal output displayed.


1 comment: