Chapter 10
Pointers

  1. Pointers
      A pointer is a memory location that points (or has the address of another storage location).


      1. A pointer is declared with the * and points to a type of variable. For example:
        int *x,y,z;
        
        x=&y;   /* x points at y */
        *x=1;   /* since indirection is used y is changed */
        x++;    /* since not *, the value x is changed    */
        


      2. The size of a pointer is usually the size of the word on the machine. This is also the integer size.o

      3. Since a pointer is a variable its value can also be changed. But the operations that can be done on a pointer are limited to.


        1. Addition or subtraction. An integer value may be added to or subtracted from a pointer.
          {
           int *i,j;
          
           i=&j;
           cout << "i=" << i <<endl;
           i++;
           cout << "i=" << i <<endl;
           i=i-3;
           cout << "i=" << i <<endl;
          
          
          A word of caution, when we add one to a pointer we aren't really adding 1. We are adding 1 unit the size of the object the pointer points at. The illustrated code yields:
          i=0x2ff7fc0c
          i=0x2ff7fc10
          i=0x2ff7fc04
          


        2. Subtraction.
          {
           int *i,*j,x,y,z;
          
           i=&x;
           j=&z;
           y=j-i;
           cout << "i=" << i << endl;
           cout << "j=" << j << endl;
           cout << "y=" << y << endl;
          }
          
          i=0x2ff7fc00
          j=0x2ff7fc08
          y=2
          
          

  2. Dynamic Arrays
    1. Pointers can be used to manipulate contiguous memory. This is how the C++ compiler "sees" arrays.
      All notation of the form x[i] is changed to *(x + i).
    2. {
       int *x,*y,i;
      
       x = new int[10];
      
       for(i=0;i<10;i++) *(x+i) = i+1;
      
       for(i=1,y=x;i<=10;i++,y++) 
           cout << "address=" << y << " value=" <<*y << endl;
      
       delete[] x;
      }
      
      address=0x20056278 value=1
      address=0x2005627c value=2
      address=0x20056280 value=3
      address=0x20056284 value=4
      address=0x20056288 value=5
      address=0x2005628c value=6
      address=0x20056290 value=7
      address=0x20056294 value=8
      address=0x20056298 value=9
      address=0x2005629c value=10
      
      

    3. Memory may be allocated dynamically and still used in array notation.
      {
       int *p,k,i;
      
        cout << "Please enter the size of the array";
        cin >> k;
        cout << "Dynamic size is " << k << endl; 
      
        p= new int[k];
      
        for(i=0;i<k;i++) p[i]=rand()%100;
      
        for(i=0;i<k;i++) 
          cout << i << " " << p[i] << endl;
      
       delete[] p;
      }
      
      Please enter the size of the array5
      Dynamic size is 5
      0 38
      1 58
      2 13
      3 15
      4 51
      
      Please enter the size of the array7
      Dynamic size is 7
      0 38
      1 58
      2 13
      3 15
      4 51
      5 27
      6 10
      d
      

  3. The pointer to a pointer notation is used to manipulate two dimension data structures in memory.

    1. Example One.
      {
       int rows=6,cols=7,**p;
       int i,j;
      
       p= new int*[rows];
       
       for(i=0;i<rows;i++) 
          p[i] = new int[cols];
      
       for(i=0;i<rows;i++)
         for(j=0;j<cols;j++)
              p[i][j]=i*j;
      
       for(i=0;i<rows;i++) {
           for(j=0;j<cols;j++) 
              cout << setw(3) << p[i][j];
            cout << endl;
       } 
       
       for(i=0;i<rows;i++) delete[] p[i];
       delete[] p;
      }
      
      
        0  0  0  0  0  0  0
        0  1  2  3  4  5  6
        0  2  4  6  8 10 12
        0  3  6  9 12 15 18
        0  4  8 12 16 20 24
        0  5 10 15 20 25 30
      

    2. A second method is:
      {
       int rows=6,cols=7,**p,*q;
       int i,j;
      
       p= new int*[rows];
      
       q=new int[rows*cols];
       
       for(i=0;i<rows;i++)  p[i]=&q[i*cols];
      
       for(i=0;i<rows;i++)
         for(j=0;j<cols;j++)
              p[i][j]=i*j;
      
       for(i=0;i<rows;i++) {
           for(j=0;j<cols;j++) 
              cout << setw(3) << p[i][j];
            cout << endl;
       }
       delete[] q;
       delete[] p;
      }
      
      
        0  0  0  0  0  0  0
        0  1  2  3  4  5  6
        0  2  4  6  8 10 12
        0  3  6  9 12 15 18
        0  4  8 12 16 20 24
        0  5 10 15 20 25 30
      

    3. Pascal's Triangle
      {
        int **tri,*temp,row,col,k;
        int cells;
      
        cout << "enter the number of rows ";
        cin >> k;
      
        tri= new int*[k];
        cells=(k * (k+1))/2;
        temp=new int[cells];
       
       for(row=0;row<k;row++)
            tri[row] = &temp[(row*row+row)/2];
      
       for(row=0;row<k;++row)
           for(col=0;col<=row;++col)
              if (col==0 || row == col)
                 tri[row][col]=1;
               else tri[row][col] = tri[row-1][col-1] + tri[row-1][col];
      
        for(row=0;row<k;++row) {
            for(col=0;col<=row;++col)
                cout << tri[row][col] << " ";
            cout << endl;
        }
      }
      
      
      enter the number of rows
      8
      1 
      1 1 
      1 2 1 
      1 3 3 1 
      1 4 6 4 1 
      1 5 10 10 5 1 
      1 6 15 20 15 6 1 
      1 7 21 35 35 21 7 1 
      

  4. Pointer and Arrays as parameters
    1. Parameter. Typically the word parameter refers to both the value passed to a function and to the variable inside the function that receives that value.

    2. Actual and Formal are used to distinguish the two kinds of parameters.

    3. Argument and parameter.

      All Scalars are passed by value. All arrays are passed by a constant reference address.

      void main()
      {
      int sub1(int, int);  /* prototype */
      int x=1,y=2,z;
      z=sub1(x,y);       /* arguments */
      cout << x << " " << y << " " << z << endl;
      }
      int sub1(int a,int b)           /* parameters */
      {
      a++;
      b++;
      return(a+b);
      }
      
      1 2 5
      
    4. In order to change the value in a variable, the invoking function will pass the address of the variable the using function will need to use indirection
      void main()
      { 
        int sub1(int, int*); /* prototype */
        int x=1,y=2,z;
        z=sub1(x,&y);       /* arguments */
        cout << x << " " << y << " " << z << endl;
        return;
      }
      int sub1(int a,int *b)           /* parameters */
      {
        a++;
        *b+=1;
        return(a+*b);
      }
      
      1 3 5
      


    5. Reference type

      This feature removes the need for passing by address and using pointer notation.
      void fun(int&);
      void main()
      { 
        int i=1,j;
        fun(i);
        cout << i <<endl;
      }
      void fun(int& x)
      {
       x++;
       return;
      }
      

    6. Pointers to Functions
      #include <math.h>
      #include <iostream.h>
      void main()
      {
        void table(float (*)(int), int, int , int); // Prototype
        float sqroot(int ),square(int);             // Prototype
        cout << "Number\tSquare Root" << endl;
        table(sqroot,1,10,2);
        cout << endl << "Number\tSquare" << endl;
        table(square,1,10,2);
      }
      void table(float (*fp)(int),int a,int b,int c)
      {
         while(a<=b) {
           cout << a << "\t" << (*fp)(a) << endl;
           a+=c;
         }
      }
      float sqroot(int v)
      {
        return(sqrt((float)v));
      }
      float square(int v)
      {
        return((float)(v*v));
      }
      
      Number  Square Root
      1       1
      3       1.73205
      5       2.23607
      7       2.64575
      9       3
      
      Number  Square
      1       1
      3       9
      5       25
      7       49
      9       81
      

  5. Pointers to objects
    #ifndef POBJ
    #define POBJ
    
    
    
    class dyn {
    public:
    	  int field1;
    	  float field2;
    	  dyn    *ptr;
    
    	       dyn(); // constructor
          void display();
    	  void link();
    	  void unlink();
    };
    #endif
    
    #include <iostream.h>
    #include "pobj.h"
    
    dyn::dyn() 
    {
    	cout << "Entered constructor" <<endl;
    	field1=2;
    	field2=3.14;
        ptr=NULL;
    		
    }
    
    void dyn::link() 
    {
    	dyn *np;
    	cout << "Called Link" <<endl;
    
    	np= new dyn();
    
    	(*np).field1=5;
    	np->field2=7.5;
    	np->ptr=NULL;
    	ptr=np;
    }
    
    void dyn::unlink()
    {
    	cout << "Called unlink" <<endl;
    	if(ptr) {
    		delete ptr;
    		ptr=NULL;
    	}
    }
    
    void dyn::display()
    {
    	cout << "Entered Display" << endl;
    	cout << "Field1 " << field1 << endl;
    	cout << "Field2 " << field2 << endl;
    	if(ptr) {
    		cout << "Displaying Link ";
    		ptr->display();
    	}
    }
    
    #include <iostream.h>
    #include "pobj.h"
    
    
    void main() 
    {
    	dyn *ptrobj;
    
    	cout << "IN main" <display();
    
    	(*ptrobj).display();
    
    	ptrobj->link();
    
    	ptrobj->display();
    
    	ptrobj->unlink();
    
    	ptrobj->display();
    }
    
    IN main
    Entered constructor
    Entered Display
    Field1 2
    Field2 3.14
    Entered Display
    Field1 2
    Field2 3.14
    Called Link
    Entered constructor
    Entered Display
    Field1 2
    Field2 3.14
    Displaying Link Entered Display
    Field1 5
    Field2 7.5
    Called unlink
    Entered Display
    Field1 2
    Field2 3.14