Showing posts with label Pointer. Show all posts
Showing posts with label Pointer. Show all posts

Tuesday, August 11, 2015

const pointer to const data in c++

A pointer is a variable and it has got a value as other variable types. A pointer can be declared as a constant.

It is allowed to dereference a constant pointer and assign a new value to the pointed address under suitable conditions.

1-) const pointer to data :

In the following function "constPtrToData()" ptr is initially pointing to the address of the val1 which is holding the value of 10. Later constant pointer ptr is dereferenced and the value at the pointed address changed.

Therefore, the value of val1 and val2 variables becomes the same at the end of the "constPtrToData()" function call.

However, it is not allowed to directly change the address where the constant pointer points to.

If the constant pointer is assigned to the address of the second variable then a compile time error arises.

If you try to assign a new address to the const ptr then the following compile-time error is generated :

error: assignment of read-only variable 'ptr'

This means that you can not change the address assigned to the const pointer.

Terminal output of the "constPtrToData()" function shows that the initial address const ptr holds does not change, but the value stored at this address changes.


#include <iostream>
using namespace std;

void constPtrToData()
{
    //not allowed to change where the ptr points to
    int val1 = 10, val2 = 20;
    int *const ptr = &val1;

    cout << "\n";
    cout << "ptr value = " << *ptr << " address = "<< ptr << "\n";

    *ptr = val2;
    cout << "\n";
    cout << "ptr value = " << *ptr << " address = "<< ptr << "\n";
    cout << "\n";
    cout << "val1 value = " << val1 << " val2 value = " << val2 << "\n";

    // can not assign to constant ptr a new address
    // ptr = &val2;  // error: assignment of read-only variable 'ptr'
}

int main()
{
    constPtrToData();
    cout << "\n";

    return 0;
}



2-) pointer to const data

A pointer can point to constant data. At this time, the address that the pointer points to can be changed but the value can not.

Following compile-time error generated when you try to dereference a pointer which points to const data.

error: assignment of read-only location '* ptr2' 

Main aim of using pointer to const data is to protect the data being pointed to instead of the address of the pointer itself.

In the following "ptrToConstantData()" function, ptr2 is declared as a normal pointer which points to constant data.

For this case, it is allowed to change the address which pointer points to.


#include <iostream>
using namespace std;


void ptrToConstantData()
{
    //protect the value of the variable pointed to
    double val3 = 32, val4 = 45;
    const double *ptr2 = &val3;
    cout << "\n";
    cout << "ptr2 value = " << *ptr2 << " address = " << ptr2 << "\n";

    // can not change the value at the address ptr2 points to
    // *ptr2 = val4;   error: assignment of read-only location '* ptr2'

    // allowed to change the address of the ptr2 points to
    ptr2 = &val4;
    cout << "\n";
    cout << "ptr2 value = " << *ptr2 << " address = " << ptr2 << "\n";
    cout << "\n";
    cout << "val3 value = " << val3 << " val4 value = " << val4 << "\n";
}

int main()
{
    ptrToConstantData();
    cout << "\n";

    return 0;
}


Output of the function call is :



3-) const pointer to const data

Declaring a constant pointer which is pointing to constant data means that you are aiming to protect both the pointer and the data at the pointed address from being modified.

In this case, if you try to change the address of the pointer or dereference the pointer following error messages generated respectively :

error: assignment of read-only variable 'ptr3'

error: assignment of read-only location '*(const int*)ptr3'

Following "constPtrToConstData()" declares ptr3 as a const pointer to const int .


#include <iostream>

using namespace std;


void constPtrToConstData()
{
    //protect both pointer and the data from being modified
    int val1 = 10, val2 = 20;
    const int *const ptr3 = &val1;

    cout << *ptr3 << "\n";

    // ptr3 = &val2;  // error: assignment of read-only variable 'ptr3'
    // *ptr3 = val2;  // error: assignment of read-only location '*(const int*)ptr3'
}

int main()
{    
    constPtrToConstData();
    cout << "\n";

    return 0;
}

When the "constPtrToConstData()" function executed it just prints "10" as expected to the terminal.

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.


Monday, February 3, 2014

Traverse Array Of C-Strings Char By Char (char* array[])

char* arrayOfCStrings[] is used as an array of pointer to character. Because it is an array and each index of the array contains a pointer to the starting character of a c-string which is terminated by an end-of-string ‘\0’ character.

Following sample project created by qt creator and contains following files:
1- TraverseArrayOfCStringsCharByChar.pro
2- main.cpp
           

TraverseArrayOfCStringsCharByChar.pro file contains project configuration.

TARGET = TraverseArrayOfCStringsCharByChar
SOURCES += main.cpp

main.cpp file contains main method which is showing how to traverse an array of c-strings till an end-of-string character is found for each string.

#include <stdio.h>

int main(int argc, char *argv[])
{

    char* arrayOfCStrings[] = {"string1","string2","string3"};

    int stringCount = sizeof(arrayOfCStrings)/sizeof(char*);

    printf("Total number of strings in the string array : %d \n",stringCount);

    int i = 0;
    while(i<stringCount)
    {
        const char* currentString = arrayOfCStrings[i];
        while((*currentString))
        {
            printf(" %c ", *currentString);
            currentString++;
        }
        printf("\n");
        ++i;
    }

    return 0;
}
arrayOfStrings is initialized by curly braces.

char* arrayOfCStrings[] = {“string1”, “string2”, “string3”};

Total number of strings in the array is computed by dividing the total size of the arrayOfStrings to the size of each char* element.
int stringCount = sizeof(arrayOfCStrings)/sizeof(char*);

Outer while loop iterates till it reaches the total number c-strings. And the inner while loop iterates for each character in the current c-string till the end-of-string '\0' character is found. Console output displays the total number of c-strings in the array and each character of the current c-string in a new line.

Thursday, October 20, 2011

Triple Pointer Operations in C++

Double pointer can be used to point to two dimensional matrix (pointer-to-pointer). If there are more than one matrices and it is required to keep track of these matrices then an additional extra pointer will be required. At his point triple-pointers can be used to point to list of two dimensional matrices.
We assume that you have got three different two-dimensional matrices as in the below picture:
Triple pointer with size of 3 and pointing to 3 different matrices:



#include <QCoreApplication>
#include <iostream>
using namespace std;

//function prototype
int** initializeMatrix(int** tempMatrix, int row, int column, int matrixCellValue);


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    int size = 3;
    int*** triplePointer;

    //Allocate memory for triplePointer
    triplePointer = new int**[size];

    int rowNum = 4;
    int columnNum = 3;
    int** newMatrix = 0;

    //Assign elements to cell values of each matrix
    for(int i=0; i<size; i++)
        triplePointer[i] = initializeMatrix(newMatrix,rowNum,columnNum,i);

    //Print elements of allocated matrices
    for(int num = 0; num<size; num++) {
        for(int i=0; i<rowNum; i++) {
            for(int j=0; j<columnNum; j++) {
                    cout<<triplePointer[num][i][j];
            }
            cout << "\n";
        }
        cout << "\n";
    }

    return a.exec();


}

/*
tempMatrix: matrix to allocate
row: number of rows of the matrix
column: number of columns of the matrix
matrixCellValue: value to assign to specified cell of matrix
 */
int** initializeMatrix(int** tempMatrix, int row, int column, int matrixCellValue)
{
    tempMatrix = new int*[row];
    for(int i=0; i<row; i++)
            tempMatrix[i] = new int[column];
    for(int i=0; i<row; i++)
            for(int j=0; j<column; j++)
                    tempMatrix[i][j] = matrixCellValue;

    return tempMatrix;
}


Sample c++ console application built with qt-creator on ubuntu and the console-output is 3 different 2x2 matrices displayed. Same output is produced when built with MSVS2008 on winXP.



Wednesday, October 12, 2011

Double Pointer Operations in C++

When initialized properly double pointers can be used as a 2 dimensional matrix. Sample qt-console application shows a way to allocate, initialize and deallocate a double pointer in C++.

Following diagrams help me to remember the subject of dynamically allocating multi-dimensional arrays in C++. 
Pointer-to-integer (simple integer array) declaration and representation: Can be considered as an array of integers.
int* ptrToInt;
pointer to integer
Pointer-to-pointer-to-integer (multi-dimensional matrix) declaration and representation: Can be considered as array of arrays of integers.
int** ptrToPtrToInt;
pointer to pointer to interger

#include <QCoreApplication>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int** myRectRegion;

    int numRows = 4;
    int numCols = 3;

    //allocate double pointer
    myRectRegion = new int* [numRows];
    for(int i=0;i<numRows;i++)
            myRectRegion[i] = new int[numCols];


    //initialize double pointer
    for(int i=0; i<numRows; i++)
            for(int j=0;j<numCols;j++)
                    myRectRegion[i][j] = 1;


    //print double pointer elements
    for(int i=0; i<numRows; i++){
        for(int j=0; j<numCols; j++){
           cout << myRectRegion[i][j];
        }
        cout << "\n";
    }


    //free deallocate double pointer
    for(int i=0;i<numRows;i++)
            delete[] myRectRegion[i];
    delete[] myRectRegion;

    return a.exec();
}

When the application is run, a 4X3 matrix is displayed in the terminal window.

There is also a helpful tutorial about dynamic allocation of multi-dimensional arrays in C at : http://c-faq.com/~scs/cclass/int/sx9b.html