home *** CD-ROM | disk | FTP | other *** search
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
- For certain types of programs, pointers and dynamic
- allocation can be a tremendous advantage, but many 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 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?
-
- Examine the program named POINT for your first example
- of a program using pointers. In the var declaration you
- will see two variables named Where and Who that have the
- symbol ^ in front of their types. This defines them, not as
- variables, but as pointers to integer type variables. In
- line 12 of the program, the variable Index is assigned the
- value of 17 for purposes of illustration. The pointer named
- Where is then assigned the address of the variable Index
- which means that it does not contain the value of 17, it
- contains the address of the storage location where the
- variable Index is stored. In like manner, we assign the
- address of Index to the pointer named Who. It should be
- obvious to you that Addr is a TURBO Pascal function that
- returns the address of its argument.
-
- HOW DO WE USE THE POINTERS?
-
- It should be clear to you that we now have a single
- variable named Index with two pointers pointing at it. If
- the pointers are useful, we should be able to do something
- with them now, so we simply print out the same variable
- three different ways in line 15. When we write "Where^", we
- are telling the system that we are not interested in the
- pointer itself but instead we are interested in the data to
- which the pointer points. This is referred to as
- dereferencing the pointer. Careful study of the output
- fields in line 15 will reveal that we first display the
- value of Index, then the value to which the pointer Where
- points, and finally the value to which the pointer Who
- points. Since both pointers point to the variable Index, we
- are essentially displaying the value of Index three times.
- You will confirm this when you compile and run this program.
-
-
- Page 73
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
-
- In line 17, we tell the system to assign the value of
- 23 to the variable to which the pointer Where points as an
- illustration. If you understood the discussion in the
- previous paragraph, you will understand that we are actually
- assigning the variable named Index the value of 23 because
- that is where the pointer named Where is pointing. In line
- 18, we once again display the value of the variable Index 3
- times just as we did in line 15. It would be to your
- advantage to compile and run this program to see that the
- value of 17 is output three times, then the value of 23 is
- output three times.
-
- In a program as simple as this, the value of pointers
- is not at all clear but a simple program is required in
- order to make the technique clear. Display the program
- named POINT on your monitor again because we are not yet
- finished with it.
-
- A FEW MORE POINTERS
-
- In line 4, we define a new type named Int_Point which
- is a pointer to an integer type variable. We use this new
- type in line 9 to define three more pointers and in line 20,
- we assign one of them the address of the variable named
- Index. Since the pointers are of identical types, in line
- 21 we can assign Pt2 the value of Pt1, which is actually the
- address of the variable named Index. Likewise, the pointer
- Pt3 is assigned the value of Pt2, and we have all three
- pointers pointing to the variable named Index. If you are
- using TURBO Pascal version 4.0, you are allowed to assign
- pointers like this only if they have the same type, which
- these three do. However, since the pointers named Where and
- Who are assigned individually, they are not of the same type
- according to the rules of Pascal and if line 14 were changed
- to read "Who := Where;", a compilation error would occur
- with TURBO Pascal version 4.0. This error would not occur
- with TURBO Pascal 3.0 since it is a little less stringent in
- its type checking.
-
- Finally, we assign the only variable in this program
- which is named Index the value of 151 in line 23 and display
- the value 151 three times as we did above. Compile and run
- this program again to see that it does indeed display the
- value 151 three times.
-
- THIS IS JUST FOR TURBO PASCAL VERSION 4.0
-
- If you are using TURBO Pascal version 4.0, you should
- display the program named POINT4 on your monitor for an
- example of another new extension to the Pascal programming
-
-
- Page 74
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
- language by Borland. This program is identical to the last
- except in lines 13, 14 and 20, where the symbol @ is used to
- denote the address of the variable index rather than the
- function "Addr". This is only available in TURBO Pascal
- version 4.0 as a convenience to you. In ANSI standard
- Pascal the @ symbol is used as a synonym for the ^ symbol
- but Borland chose to use it for a completely different
- purpose. If you are using TURBO Pascal 3.0, you will not be
- able to compile and run this program, but nothing is lost
- because it is identical to the previous one.
-
- OUR FIRST LOOK AT DYNAMIC ALLOCATION
-
- If you examine the file named POINTERS, you will see a
- very trivial example of pointers and how they are used with
- dynamically allocated variables. In the var declaration,
- you will see that the two variables have a ^ in front of
- their respective types once again, defining two pointers.
- They will be used to point to dynamically allocated
- variables that have not yet been defined.
-
- The pointer My_Name is a pointer to a 20 character
- string. The pointer actually points to an address somewhere
- within the computer memory, but we don't know where yet.
- Actually, there is nothing for it to point at because we
- have not defined a variable. After we assign it something
- to point to, we can use the pointer to 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 version 3.0, it requires about 35K,
- but if you are using version 4.0, it requires about 110K.
- The TURBO Pascal program can use up to 64K. Adding those
- three numbers together results in about 159K or 234K. Any
- memory you have installed in excess of that is available for
- the stack and the heap. The stack is a standard area
- defined and controlled by DOS that can grow and shrink as
- needed. Many books are available to define the stack and
- its use if you are interested in more information on it.
-
- WHAT IS THE HEAP?
-
- 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
-
-
- Page 75
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
- of the 64K limitation of TURBO Pascal and many other Pascal
- compilers.
-
- TURBO Pascal version 4.0 does not limit us to 64K, but
- there are other reasons for using the heap in addition to
- the 64K limitation. These should be evident as we learn how
- the heap works.
-
- If you did not understand the last few 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 in line 10 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 ^, just like in the last program, and is read,
- "the variable to which the pointer points".
-
- The statement in line 11 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 in much the
- same manner as we did in the program named POINT.
-
- GETTING RID OF DYNAMICALLY ALLOCATED DATA
-
- The two statements in lines 19 and 20 are illustrations
- of the way the dynamically allocated variables are removed
- from use. When they are no longer needed, they are disposed
-
-
-
- Page 76
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
- of with the Dispose procedure which frees up their space on
- the heap so it can be reused.
-
- 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
- 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 point must be kept
- in mind. 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.
-
- Compile and run this program and examine the output.
-
- 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.
-
- A point should be made here. Pointers are not
- generally used in very small programs. This program is a
- good bit larger than the last and should be a clue to you as
- to why such a trivial program was used to introduce pointers
- in this tutorial. A very small, concise program can
- illustrate a topic much better that an large complex
- program, but we must go on to more useful constructs of any
- new topic.
-
- WE JUST BROKE THE GREAT RULE OF PASCAL
-
- Notice in the type declaration that we used the
- identifier Person in line 18 before we defined it in line
- 19, 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
-
-
- Page 77
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
- particular 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 use the
- New procedure to dynamically allocate a record with Self
- pointing to it, and use the pointer so defined to fill the
- dynamically allocated record. Compare this to the program
- named 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.
-
- THIS IS A TRICK, BE CAREFUL
-
- Now go down to line 48 where Mother is allocated 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 because we did a pointer assignment. The data that
- was allocated to the pointer Mother is now somewhere on the
- heap, but we don't know where, and 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 where the data is stored.
-
- 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 lines 57
- through 63 of the program where some data is written 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 and we return to DOS or the
- TURBO Pascal integrated environment. 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.
-
-
- Page 78
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
-
- 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.
-
- 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
- named 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
- in lines 4 and 6, 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 another
- record of this type. 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,
-
-
- Page 79
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
- 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.
-
- Lets look at the program itself now. In line 20, 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.
-
- WHAT IS "nil" AND WHAT IS IT USED FOR?
-
- 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". The word nil is another
- reserved word that doesn't give the pointer an address but
- defines it as empty. A pointer that is currently nil cannot
- be used to manipulate data because 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 to
- find the next clue. 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.
-
- In lines 27 through 33 we will 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
-
-
- Page 80
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
- 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 dynamically allocate 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 which we do in line 29. 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 person's name and a pointer to the
- second record, and a second record with a different person's
- 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.
-
- 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.
-
- FINALLY, A COMPLETE LINKED LIST
-
- 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 local memory, but it is
- costly in terms of programming. (Keep in mind that all of
- the data must be stored somewhere in memory, and in the case
- of the linked list, it is stored on the heap.) 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.
-
-
-
-
- Page 81
-
-
-
-
-
-
-
-
-
- CHAPTER 12 - Pointers and Dynamic Allocation
-
-
- Following is a graphical representation of what the
- linked list looks like.
-
- Start_Of_List---->John
- Q
- Doe
- Next---->Mary
- R
- Johnson
- Next---->William
- S
- Jones
- Next---->
- .
- .
- .
- ---->William
- S
- Jones
- Next---->nil
-
- 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 82
-
-
-
-
-
-
-
-
-
- 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 83
-