              CHAPTER 12 - Pointers and Dynamic Allocation



            For  certain  types of programs,  pointers  and  dynamic 

        allocation can be a tremendous advantage,  but most programs 

        do not need such a high degree of data structure.   For that 

        reason,  it  would probably be to your advantage to  lightly 

        skim over these topics and come back to them later when  you 

        have  a  substantial base of Pascal programming  experience.  

        It would be good to at least skim over this material  rather 

        than  completely neglecting it,  so you will have an idea of 

        how  pointers and dynamic allocation work and that they  are 

        available for your use when needed.

            A  complete understanding of this material will  require 

        deep  concentration  as it is very complex and  not  at  all 

        intuitive.   Nevertheless,  if you pay close attention,  you 

        will have a good grasp of pointers and dynamic allocation in 

        a short time.

                WHAT ARE POINTERS, AND WHAT GOOD ARE THEY?

            If  you  examine POINTERS,  you will see a very  trivial 

        example  of  pointers and how they are  used.   In  the  VAR 

        declaration, you will see that the two variables have a ^ in 

        front  of  their respective types.   These are not  actually 

        variables,  instead,  they  point to  dynamically  allocated 

        variables  that  have  not been defined yet,  and  they  are 

        called pointers.

            The  pointer  "my_name" is a pointer to a  20  character 

        string  and is therefore not a variable into which  a  value 

        can be stored.   This is a very special Pascal TYPE,  and it 

        cannot be assigned a character string,  only a pointer value 

        or  address.   The  pointer  actually points to  an  address 

        somewhere  within the computer memory,  and can  access  the 

        data stored at that address.

            Your computer has some amount of memory installed in it. 

        If it is an IBM-PC or compatible,  it can have up to 640K of 

        RAM which is addressable by various programs.  The operating 

        system requires about 60K of the total, and if you are using 

        TURBO  Pascal  it  requires about  35K.   The  TURBO  Pascal 

        program  can  use  up to 64K.   Adding those  three  numbers 

        together  results  in  about  159K.   Any  memory  you  have 

        installed  in excess of that is available for the stack  and 

        the  heap.    The  stack  is  a  standard  DOS  defined  and 

        controlled  area that can grow and shrink as  needed.   Many 

        books  are  available  to  define  the  stack  if  you   are 

        interested in more information on it.






                                 Page 60









              CHAPTER 12 - Pointers and Dynamic Allocation


            The  heap  is  a  Pascal defined  entity  that  utilizes 

        otherwise   unused  memory  to  store   data.    It   begins 

        immediately  following  the program and grows  as  necessary 

        upward toward the stack which is growing downward.   As long 

        as they never meet,  there is no problem.   If they meet,  a 

        run-time error is generated.   The heap is therefore outside 

        of  the 64K limitation of TURBO Pascal and many other Pascal 

        compilers.

            If you did not understand the last two paragraphs, don't 

        worry.  Simply remember that dynamically allocated variables 

        are  stored  on  the  heap  and do  not  count  in  the  64K 

        limitation placed upon you by some compilers.

            Back to our example program, POINTERS.  When we actually 

        begin executing the program,  we still have not defined  the 

        variables  we  wish  to use to store  data  in.   The  first 

        executable  statement  generates a variable for us  with  no 

        name  and stores it on the heap.   Since it has no name,  we 

        cannot do anything with it,  except for the fact that we  do 

        have  a pointer "my_name" that is pointing to it.   By using 

        the pointer, we can store up to 20 characters in it, because 

        that is its type, and later go back and retrieve it.

                        WHAT IS DYNAMIC ALLOCATION?

            The  variable  we have just described is  a  dynamically 

        allocated  variable  because  it was not defined  in  a  VAR 

        declaration,   but  with  a  "new"  procedure.    The  "new" 

        procedure  creates  a variable of the type  defined  by  the 

        pointer,  puts  it  on  the heap,  and finally  assigns  the 

        address  of  the  variable  to  the  pointer  itself.   Thus 

        "my_name"  contains the address of the  variable  generated.  

        The variable itself is referenced by using the pointer to it 

        followed  by a ^,  and is read,  "the variable to which  the 

        pointer points".

            The  next  statement assigns a place on the heap  to  an 

        INTEGER  type  variable  and puts its address  in  "my_age".  

        Following  the  "new"  statements  we  have  two  assignment 

        statements  in  which  the  two  variables  pointed  at  are 

        assigned values compatible with their respective types,  and 

        they  are both written out to the video display.   The  last 

        two statements are illustrations of the way the  dynamically 

        allocated variables are removed from use.   When they are no 

        longer  needed,  they  are  disposed of with  the  "dispose" 

        procedure.

            In   such   a  simple  program,   pointers   cannot   be 

        appreciated,  but it is necessary for a simple illustration.  

        In a large,  very active program,  it is possible to  define 



                                 Page 61









              CHAPTER 12 - Pointers and Dynamic Allocation


        many variables,  dispose of some of them,  define more,  and 

        dispose of more, etc.  Each time some variables are disposed 

        of,  their  space  is  then made  available  for  additional 

        variables defined with the "new" procedure.

            The  heap can be made up of any assortment of variables, 

        they  do  not have to all be the same.   One thing  must  be 

        remembered,  anytime a variable is defined,  it will have  a 

        pointer  pointing to it.   The pointer is the only means  by 

        which  the variable can be accessed.   If the pointer to the 

        variable is lost or changed, the data itself is lost for all 

        practical purposes.

                       DYNAMICALLY STORING RECORDS;

            The next example program,  DYNREC, is a repeat of one we 

        studied  in an earlier chapter.   For your own  edification, 

        review the example program BIGREC before going ahead in this 

        chapter.   Assuming  that you are back in DYNREC,  you  will 

        notice  that this program looks very similar to the  earlier 

        one,  and in fact they do exactly the same thing.   The only 

        difference  in  the TYPE declaration is the  addition  of  a 

        pointer "person_id",  and in the VAR declaration,  the first 

        four  variables  are  defined as  pointers  here,  and  were 

        defined as record variables in the last program.

                  WE JUST BROKE THE GREAT RULE OF PASCAL

            Notice   in  the  TYPE  declaration  that  we  used  the 

        identifier "person" before we defined it,  which is  illegal 

        to  do in Pascal.   Foreseeing the need to define a  pointer 

        prior  to  the record,  the designers of Pascal allow us  to 

        break  the rule in this one place.   The pointer could  have 

        been defined after the record in this case,  but it was more 

        convenient  to  put  it before,  and  in  the  next  example 

        program,  it  will be required to put it before the  record.  

        We will get there soon.

            Since  "friend"  is  really 50  pointers,  we  have  now 

        defined  53 different pointers to records,  but so far  have 

        defined  no  variables other than "temp"  and  "index".   We 

        immediately define a record with "self" pointing to it,  and 

        use  the  pointer  so defined to fill  the  record  defined.  

        Compare  this  to  "BIGREC"  and you will  see  that  it  is 

        identical  except  for the addition of the "new" and  adding 

        the  ^  to  each use of the pointer to  designate  the  data 

        pointed to.







                                 Page 62









              CHAPTER 12 - Pointers and Dynamic Allocation


                        THIS IS A TRICK, BE CAREFUL

            Now  go down to the place where "mother" is  assigned  a 

        record and is then pointing to the record.  It seems an easy 

        +thing to do then to simply assign all of the values of self 

        to  all the values of mother as shown in the next statement, 

        but it doesn't work.   All the statement does,  is make  the 

        pointer  "mother"  point to the same place where  "self"  is 

        pointing.   The  data  that  was allocated  to  the  pointer 

        "mother"  is  now somewhere on the heap,  but we don't  know 

        where, so we cannot find it, use it, or deallocate it.  This 

        is an example of losing data on the heap.  The proper way is 

        given  in  the  next  two statements  where  all  fields  of 

        "father"  are  defined by all fields of  "mother"  which  is 

        pointing  at  the original "self" record.   Note that  since 

        "mother"  and "self" are both pointing at the  same  record, 

        changing  the  data with either pointer results in the  data 

        appearing to be changed in both because there is,  in  fact, 

        only one field.

            In  order  to  WRITE  from or READ  into  a  dynamically 

        assigned  record it is necessary to use a  temporary  record 

        since  dynamically  assigned records are not allowed  to  be 

        used in I/O statements.   This is illustrated in the section 

        of the program that writes some data to the monitor.

            Finally,   the   dynamically  allocated  variables   are 

        disposed  of  prior  to ending the program.   For  a  simple 

        program such as this, it is not necessary to dispose of them 

        because all dynamic variables are disposed of  automatically 

        when  the  program  is  terminated.    Notice  that  if  the 

        "dispose(mother)" statement was included in the program, the 

        data  could  not be found due to the lost pointer,  and  the 

        program would be unpredictable, probably leading to a system 

        crash.

                       SO WHAT GOOD IS THIS ANYWAY?

            Remember  when  you were initially studying  BIGREC?   I 

        suggested  that you see how big you could make the  constant 

        "number_of_friends" before you ran out of memory.   At  that 

        time  we  found that it could be made slightly greater  than 

        1000   before  we  got  the  memory  overflow   message   at 

        compilation.  Try the same thing with DYNREC to see how many 

        records  it  can handle,  remembering that the  records  are 

        created dynamically,  so you will have to run the program to 

        actually run out of memory.  The final result will depend on 

        how  much  memory you have installed,  and how  many  memory 

        resident programs you are using such as "Sidekick".   If you 

        have  a  full  memory of 640K,  I would  suggest  you  start 

        somewhere above 8000 records of "friend".



                                 Page 63









              CHAPTER 12 - Pointers and Dynamic Allocation



            Now   you  should  have  a  good  idea  of  why  Dynamic 

        Allocation can be used to greatly increase the usefulness of 

        your programs.   There is, however, one more important topic 

        we  must cover on dynamic allocation.   That is  the  linked 

        list.

                          WHAT IS A LINKED LIST?

            Understanding and using a linked list is by far the most 

        baffling  topic  you will confront in Pascal.   Many  people 

        simply  throw up their hands and never try to use  a  linked 

        list.   I  will  try to help you understand it by use of  an 

        example  and  lots  of  explanation.   Examine  the  program 

        LINKLIST for an example of a linked list.   I tried to  keep 

        it  short  so you could see the entire operation and yet  do 

        something meaningful.

            To begin with,  notice that there are two TYPEs defined, 

        a pointer to the record and the record itself.   The record, 

        however,  has one thing about it that is new to us, the last 

        entry, "next" is a pointer to this very record.  This record 

        then,  has  the ability to point to itself,  which would  be 

        trivial  and meaningless,  or to another record of the  same 

        type  which  would be extremely useful in  some  cases.   In 

        fact,  this is the way a linked list is used.   I must point 

        out, that the pointer to another record, in this case called 

        "next",  does  not have to be last in the list,  it  can  be 

        anywhere it is convenient for you.

            A couple of pages ago, we discussed the fact that we had 

        to  break  the  great rule of Pascal and use  an  identifier 

        before it was defined.   This is the reason the exception to 

        the  rule  was allowed.   Since the pointer  points  to  the 

        record,  and the record contains a reference to the pointer, 

        one  has  to be defined after being used,  and by  rules  of 

        Pascal,  the pointer can be defined first, provided that the 

        record  is  defined  immediately following it.   That  is  a 

        mouthful  but  if  you  just use the  syntax  shown  in  the 

        example, you will not get into trouble with it.

                            STILL NO VARIABLES?

            It may seem strange, but we still will have no variables 

        defined,  except  for our old friend "index".   In fact  for 

        this example,  we will only define 3 pointers.   In the last 

        example  we  defined 54 pointers,  and had lots  of  storage 

        room.  Before we are finished, we will have at least a dozen 

        pointers but they will be stored in our records, so they too 

        will be dynamically allocated.




                                 Page 64









              CHAPTER 12 - Pointers and Dynamic Allocation


            Lets look at the program itself now.  First, we create a 

        dynamically  allocated record and define it by  the  pointer 

        "place_in_list".   It  is composed of the three data fields, 

        and another pointer.   We define "start_of_list" to point to 

        the  first record created,  and we will leave  it  unchanged 

        throughout  the program.   The pointer "start_of_list"  will 

        always point to the first record in the linked list which we 

        are building up.

            We  define  the three variables in the record to be  any 

        name  we  desire  for illustrative  purposes,  and  set  the 

        pointer in the record to NIL.   NIL is a reserved word  that 

        doesn't  put  an  address in the pointer but defines  it  as 

        empty.  A pointer that is currently NIL cannot be written to 

        the  display as it has no value,  but it can be tested in  a 

        logical  statement to see if it is NIL.   It is therefore  a 

        dummy  assignment.   With all of that,  the first record  is 

        completely defined.

                        DEFINING THE SECOND RECORD

             When  you  were young you may have played  a  searching 

        game  in which you were given a clue telling you  where  the 

        next clue was at.   The next clue had a clue to the location 

        of  the third clue.   You kept going from clue to clue until 

        you  found the prize.   You simply exercised a linked  list.  

        We  will now build up the same kind of a list in which  each 

        record will tell us where the next record is at.

            We will now define the second record.   Our goal will be 

        to store a pointer to the second record in the pointer field 

        of  the first record.   In order to keep track of  the  last 

        record,  the one in which we need to update the pointer,  we 

        will  keep  a  pointer to it in "temp_place".   Now  we  can 

        create another "new" record and use "place_in_list" to point 

        to  it.   Since  "temp_place" is now pointing at  the  first 

        record,  we  can  use it to store the value of  the  pointer 

        which  points to the new record.   The 3 data fields of  the 

        new record are assigned nonsense data for our  illustration, 

        and the pointer field of the new record is assigned NIL.

            Lets review our progress to this point.  We now have the 

        first record with a name and a pointer to the second record, 

        and  a  second  record with a different name and  a  pointer 

        assigned NIL.   We also have three pointers, one pointing to 

        the first record,  one pointing to the last record,  and one 

        we  used  just  to get here since it  is  only  a  temporary 

        pointer.   If you understand what is happening so far,  lets 

        go  on to add some additional records to the list.   If  you 

        are confused, go back over this material again.




                                 Page 65









              CHAPTER 12 - Pointers and Dynamic Allocation


                             TEN MORE RECORDS

            The  next section of code is contained within a FOR loop 

        so  the statements are simply repeated ten  times.   If  you 

        observe  carefully,  you will notice that the statements are 

        identical  to the second group of statements in the  program 

        (except of course for the name assigned).   They operate  in 

        exactly  the same manner,  and we end up with ten more names 

        added  to  the list.   You will now see  why  the  temporary 

        pointer was necessary,  but pointers are cheap, so feel free 

        to use them at will. A pointer only uses 4 bytes of memory.

            We  now have generated a linked list of twelve  entries.  

        We  have a pointer pointing at the first entry,  and another 

        pointer pointing at the last.   The only data stored  within 

        the program itself are three pointers,  and one integer, all 

        of  the  data is on the heap.   This is one advantage  to  a 

        linked list,  it uses very little internal memory, but it is 

        costly  in  terms of programming.   You should never  use  a 

        linked  list  simply  to save memory,  but  only  because  a 

        certain  program  lends  itself well to  it.   Some  sorting 

        routines are extremely fast because of using a linked  list, 

        and it could be advantageous to use in a database.

                      HOW DO WE GET TO THE DATA NOW?

            Since  the data is in a list,  how can we get a copy  of 

        the  fourth entry for example?   The only way is to start at 

        the beginning of the list and successively examine  pointers 

        until  you  reach the desired one.   Suppose you are at  the 

        fourth and then wish to examine the third.   You cannot back 

        up,  because  you didn't define the list that way,  you  can 

        only  start at the beginning and count to  the  third.   You 

        could  have  defined  the  record  with  two  pointers,  one 

        pointing forward,  and one pointing backward.  This would be 

        a  doubly-linked  list and you could then go  directly  from 

        entry four to entry three.

            Now that the list is defined, we will read the data from 

        the  list and display it on the video monitor.   We begin by 

        defining the pointer,  "place_in_list",  as the start of the 

        list.   Now  you see why it was important to keep a copy  of 

        where the list started.   In the same manner as filling  the 

        list,  we  go from record to record until we find the record 

        with NIL as a pointer.

            There are entire books on how to use linked  lists,  and 

        most Pascal programmers will seldom, if ever, use them.  For 

        this  reason,  additional detail is considered  unnecessary, 

        but  to be a fully informed Pascal programmer,  some insight 

        is necessary.



                                 Page 66









              CHAPTER 12 - Pointers and Dynamic Allocation



                           PROGRAMMING EXERCISE

        1.  Write  a program to store a few names dynamically,  then 

            display  the stored names on the monitor.  As your first 

            exercise in dynamic allocation, keep it very simple.















































                                 Page 67

