


                                                              Chapter 3
                                                               POINTERS

      Because pointers are so important in C and C++, this chapter will
      review some of the more important topics concerning pointers.  Even
      if you are extremely conversant in the use of pointers, you should
      not completely ignore this chapter because some new material is
      presented here.


      POINTER REVIEW
      _________________________________________________________________

      Examine the program named POINTERS.CPP for a     ================
      simple example of the use of pointers.  This is    POINTERS.CPP
      a pointer review and if you are comfortable with ================
      the use of pointers, you can skip this example
      program completely.
      A pointer in either ANSI-C or C++ is declared with an asterisk
      preceding the variable name.  The pointer is then a pointer to a
      variable of that one specific type and should not be used with
      variables of other types.  Thus pt_int is a pointer to an integer
      type variable and should not be used with any other type.  Of
      course, an experienced C programmer knows that it is simple to
      coerce the pointer to be used with some other type by using a cast,
      but he must assume the responsibility for its correct usage.

      In line 12 the pointer named pt_int is assigned the address of the
      variable named pig and line 13 uses the pointer named pt_int to add
      the value of dog to the value of pig because the asterisk
      dereferences the pointer in exactly the same manner as standard C.
      The address is used to print out the value of the variable pig in
      line 14 illustrating the use of a pointer with the stream output
      operator cout.  Likewise, the pointer to float named pt_float is
      assigned the address of x, then used in a trivial calculation in
      line 18.

      If you are not completely comfortable with this trivial program
      using pointers, you should review the use of pointers in any good
      C programming book or Coronado Enterprises C tutorial before
      proceeding on because we will assume that you have a thorough
      knowledge of pointers throughout the remainder of this tutorial.
      It is not possible to write a C program of any significant size or
      complexity without the use of pointers.


      CONSTANT POINTERS AND POINTERS TO CONSTANTS
      _________________________________________________________________

      The definition of C++ allows a pointer to a constant to be defined
      such that the value to which the pointer points cannot be changed
      but the pointer itself can be moved to another variable or
      constant.  The method of defining a pointer to a constant is

                                                               Page 3-1
      
                                                   Chapter 3 - Pointers

      illustrated in line 22.  In addition to a pointer to a constant,
      you can also declare a constant pointer, one that cannot be
      changed.  Line 23 illustrates this.  Note that neither of these
      pointers are used in illustrative code.

      Either of these constructs can be used to provide additional
      compile time checking and improve the quality of your code.  If you
      know a pointer will never be moved due to its nature, you should
      define it as a constant pointer.  If you know that a value will not
      be changed, it can be defined as a constant and the compiler will
      tell you if you ever inadvertently attempt to change it.


      A POINTER TO VOID
      _________________________________________________________________

      The pointer to void is actually a part of the ANSI-C standard but
      is relatively new so it is commented upon here.  A pointer to void
      can be assigned the value of any other pointer type.  You will
      notice that the pointer to void named general is assigned an
      address of an int type in line 15 and the address of a float type
      in line 20 with no cast and no complaints from the compiler.  This
      is a relatively new concept in C and C++.  It allows a programmer
      to define a pointer that can be used to point to many different
      kinds of things to transfer information around within a program.
      A good example is the malloc() function which returns a pointer to
      void.  This pointer can be assigned to point to any entity, thus
      transferring the returned pointer to the correct type.

      A pointer to void is aligned in memory in such a way that it can
      be used with any of the simple predefined types available in C++,
      or in ANSI-C for that matter.  They will also align with any
      compound types the user can define since compound types are
      composed of the simpler types.

      Be sure to compile and execute this program.


      DYNAMIC ALLOCATION AND DEALLOCATION
      _________________________________________________________________

      Examine the program named NEWDEL.CPP for our     ================
      first example of the new and delete operators.      NEWDEL.CPP
      The new and delete operators do dynamic          ================
      allocation and deallocation in much the same
      manner that malloc() and free() do in your old
      favorite C implementation.

      During the design of C++, it was felt that since dynamic allocation
      and deallocation are such a heavily used part of the C programming
      language, it should be a part of the language, rather than a
      library add-on.  The new and delete operators are actually a part
      of the C++ language and are operators, much like the addition
      operator or the assignment operator.  They are therefore very

                                                               Page 3-2
      
                                                   Chapter 3 - Pointers

      efficient, and are very easy to use as we will see in this example
      program.

      Lines 14 and 15 illustrate the use of pointers in the tradition of
      C and line 16 illustrates the use of the new operator.  This
      operator requires one modifier which must be a type as illustrated
      here.  The pointer named point2 is now pointing at the new integer
      variable which exists on the heap, and can be used in the same way
      that any dynamically allocated variable is used in ANSI-C.  Line
      18 illustrates displaying the value on the monitor which was
      assigned in line 17.

      Line 20 allocates another new variable and line 21 causes point2
      to refer to the same dynamically allocated variable as point1 is
      pointing to.  In this case, the reference to the variable that
      point2 was previously pointing to has been lost and it can never
      be used or deallocated.  It is lost on the heap until we return to
      the operating system when it will be reclaimed for further use, so
      this is obviously not good practice.  Note that point1 is
      deallocated with the delete operator in line 25, and point2 can not
      actually be deleted.  Since the pointer point1 itself is not
      changed, it is actually still pointing to the original data on the
      heap.  This data could probably be referred to again using point1,
      but it would be terrible programming practice since you have no
      guarantee what the system will do with the pointer or the data.
      The data storage is returned to the free list to be allocated in
      a subsequent call, and will soon be reused in any practical
      program.

      Since the delete operator is defined to do nothing if it is passed
      a NULL value, it is legal to ask the system to delete the data
      pointed to by a pointer with the value of NULL, but nothing will
      actually happen.  It is considered a no-op and is actually wasted
      code.  The delete operator can only be used to delete data
      allocated by a new operator.  If the delete is used with any other
      kind of data, the operation is undefined and anything can happen.
      According to the ANSI standard, even a system crash is a legal
      result of this illegal operation, and can be defined as such by the
      compiler writer.

      In line 27, we declare some floating point variables.  You will
      remember that in C++ the variables do not have to be declared at
      the beginning of a block.  A declaration is an executable statement
      and can therefore appear anywhere in a list of executable
      statements.  One of the float variables is allocated within the
      declaration to illustrate that this can be done.  Some of the same
      operations are performed on these float type variables as were done
      on the int types earlier.

      Some examples of the use of a structure are given in lines 35
      through 41 and should be self explanatory.

      Finally, since the new operator requires a type to determine the
      size of the dynamically allocated block, you may wonder how you can

                                                               Page 3-3
      
                                                   Chapter 3 - Pointers

      allocate a block of arbitrary size.  This is possible by using the
      construct illustrated in line 47 where a block of 37 char sized
      entities, which will be 37 bytes, is allocated.  A block of 133
      bytes greater than the size of the date structure is allocated in
      line 49.  It is therefore clear that the new operator can be used
      with all of the flexibility of the malloc() function which you are
      used to using.

      The standard functions which you have been using in C for dynamic
      memory management, malloc(), calloc(), and free(), are also
      available for use in C++ and can be used in the same manner they
      were used in C.  The new and delete operators should not be
      intermixed with the older function calls since the results may be
      unpredictable.  If you are updating code with the older function
      calls, continue to use them for any additions to the code.  If you
      are designing and coding a new program you should use the newer
      constructs because they are a built in part of the language rather
      than an add on and are therefore more efficient.

      Be sure to compile and execute this program.


      POINTERS TO FUNCTIONS
      _________________________________________________________________

      Examine the program named FUNCPNT.CPP for an      ===============
      example of using a pointer to a function.  It       FUNCPNT.CPP
      must be pointed out that there is nothing new     ===============
      here, the pointer to a function is available in
      ANSI-C as well as in C++ and works in the manner
      described here for both languages.  It is not regularly used by
      most C programmers, so it is defined here for your information.

      There is nothing unusual about this program except for the pointer
      to a function declared in line 8.  This declares a pointer to a
      function which returns nothing (void) and requires a single formal
      parameter, a float type variable.  You will notice that all three
      of the functions declared in lines 5 through 7 fit this profile and
      are therefore candidates to be called with this pointer.  If you
      have not used prototyping in C, these lines will look strange to
      you.  Don't worry about them at this point since we will study
      prototyping in the next chapter of this tutorial.

      Observe that in line 15 we call the function print_stuff() with the
      parameter pi and in line 16 we assign the function pointer named
      function_pointer the value of print_stuff() and use the function
      pointer to call the same function again in line 17.  Lines 15 and
      17 are therefore identical in what is accomplished because of the
      pointer assignment in line 16.  In lines 18 through 23, a few more
      illustrations of the use of the function pointer are given.  You
      will be left to study these on your own.

      Since we assigned the name of a function to a function pointer, and
      did not get an assignment error, the name of a function must be a

                                                               Page 3-4
      
                                                   Chapter 3 - Pointers

      pointer to that function.  This is exactly the case, a function
      name is a pointer to that function, but it is a pointer constant
      and cannot be changed.  This is exactly the case we found when we
      studied arrays in ANSI-C at some point in our C programming
      background.  An array name is a pointer constant to the first
      element of the array.

      Since the name of the function is a constant pointer to that
      function, we can assign the name of the function to a function
      pointer and use the function pointer to call the function.  The
      only caveat is that the return value and the number and types of
      parameters must be identical.  Most C and C++ compilers will not,
      and in fact, can not warn you of type mismatches between the
      parameter lists when the assignments are made.  This is because the
      assignments are done at runtime when no type information is
      available to the system, rather than at compile time when all type
      information is available.

      This use and operations of pointers must be thoroughly understood
      when we get to the material on dynamic binding and polymorphism
      later in this tutorial.  It will be discussed in detail at that
      time.

      Be sure to compile and execute this program.


      PROGRAMMING EXERCISES
      _________________________________________________________________


      1.   When dynamically allocated data is deleted, it is still
           actually in memory, stored on the heap.  Repeat the output
           statement from line 23 of NEWDEL.CPP immediately following the
           delete in line 25 to see if the values are really still there.
           Repeat it once again just prior to the end of the program when
           the data spaces should have been written over to see if you
           get garbage out.  Even if your compiler reports the correct
           data, it is terrible practice to count on this data still
           being there because in a large dynamic program, the heap space
           will be used repeatedly.

      2.   Add a function to FUNCPNT.CPP which uses a single integer for
           a parameter and attempt to call it by using the function
           pointer to see if you get the correct data into the function.










                                                               Page 3-5
