Chapter 1 - Pointers

 


Hi! We meet again! Seems that you're eager to review this document. How about the first lesson? Is it great? Have you already known Pascal? If you don't - well - I suggest you to read the first part of this Pascal lesson. If you haven't followed the first part, take a look at this link to see what we've learnt so long. Please do so because I assume you've already mastered all what I've given to you in the last part. Hmm. Well, I suppose you did.

 

Introduction

Ok, let's begin! Sometimes programmers are talking about pointers. What's that? Is that a lurking monstrous programming terror we have to master? To be honest, pointers are horrors to some programmers. But keep that bad feelings aside. Let's take a look at the positive side.

I discuss pointers quite thoroughly since pointers are very powerful as programming tools. I divided our discussion into three parts: The basics, linked list concepts, and tree - especially binary tree. The basics tell you all about the fundamental concepts of pointers. Linked list concepts cover singly linked lists (LIFO or stacks, FIFO or queues), doubly linked lists, circular lists (single or double), and multi-dimensional linked lists (2-D and 3-D). Because linked lists are quite broad, perhaps I should divide it into two or more chapters. Tree concepts discussed here are about tree basics and binary tree.

Perhaps the discussions about pointers here are quite brief to suit your need, especially for academic purposes. If you need to learn more, I suggest you read "Data Structures and Program Design in Pascal" book from Macmillan Publishing Co, written by Larry Nyhoff and Sanford Leestma chapter 7 to 9, 12 and 13, about linked lists and advanced concepts. Currently... well, as far as I know, the current edition is the second edition, released in 1992. Hmm, I suppose Macmillan has already released next editions. To my opinion, it is quite a good book. To contact Macmillan, follow this link. Recently, I searched on the web, I could not find that book. I'm really sorry. If you ever find it, mail me.

 

Who should learn it?

Wow! Complete! Yes. Well, I design this parts for computer science (or related subjects) academician. If you want to know pointers just to implement it, well... yeah you right! You need not to study much, but learn only the basics, single and double linked lists, and binary tree (just in case you want to make a 3-D programs). This obviously needs less effort and hours and yet, may be very useful. But for you, academicians (especially students), you should learn them all ... if you want to pass with a good grade! J

Let's begin!

What is exactly pointer? Err, as this chapter is not physics nor mathematics, I answer you quite briefly: It's a special variable contains an address to another location in memory. Which memory? Any memory, physically or virtually (in case you use Windows™, and you know virtual memory). Most of the times, computer arranges it for us. You only need to know that pointer is a variable (usually a long integer) that points to another location in memory. It could point to itself, too. A variable that points to something, that's why it is called as pointer.

There are two kinds of pointers: typed and generic – or untyped. First, we discuss typed pointers. Typed pointers are pointers that point to a specific type of variable while untyped is not. Thus, to declare typed pointers, we need also specify what type it is. Example:


var
p : ^integer;

That declares p as a pointer of integer. Similarly, the statements of t : ^byte; declares t as a pointer of byte. Adding a caret sign (^) in front of a variable type declare it as a pointer of that type. That rule applies to records and other complex data types as well.

What's so special with this pointer? Examine this example closely and run it:


var
p : ^integer;
m, n : integer;
begin
  m:=10; n:=15;
  p:=@m;             { p now points to m }
  p^:=12;            { this is the same to m:=12; }
  p:=@n;             { p now points to n }
  p^=m;              { this is the same to n:=m; }
  writeln('m = ',m,', n = ',n);   { m = 12, n = 12 }
end.

Surprise! Wow, how could it be? Well, when p points to m (denoted by p:=@m;), accessing p^ is the same as accessing m for any operations (assigning, comparing, doing math, etc.). Accessing pointers is easy, just put the pointer variable name and a caret (^) afterwards, then treat them just like usual variables. Pretty easy, huh? J

How about records? Can pointer deal with them? Sure. Put the caret after the name of the record variable, then put a period, then the field name. Example :

Employee^.totalsalary:=Employee^.basicsalary+ Employee^.overtime*rate;

Or, just:

With employee^ do

Totalsalary:=basicsalary+overtime*rate;

That was just the basics of pointers. Many surprises will even come.

If pointers just "point and shoot", what's the use? Well, clever programmers could even reserve some amount of memory using pointers.

First of all, you must know this: What you declare in "var" section is called static variable. Static variable is limited in size of 64KB for every module, no more, period. That means, in main program we could use only 64KB and each Pascal unit could use each 64KB chunk. That's not enough!

One of the solutions is breaking our program to several units. Wow, how inefficient! Another breakthrough is reserving a big amount of memory in the "heap". Before you know what heap is, let's assume that through this (reserving memory through pointers), we could break the 64KB static variable limitations. This will mainly be discussed in untyped pointers in the later section of this document.

Or, the easiest thing - if you could accept - just don't argue why should we reserve some space in memory into pointers. Just keep in mind that this trick is important, and you would realize the benefit as I've mentioned above later on.

Look at this declaration:


Type
  Pemployee = ^Temployee;
  Temployee = record
                Name     : string[10];
                Position : char;
                Salary   : longint;
              end;
var
  p : pemployee;
begin
  new(p);
  p^.name:='Clark'
  p^.position:='S';
  p^.salary:=3000;
  writeln(p^.name,' ',p^.position,' ',p^.salary);
  dispose(p);
end.

Don't argue with me in "type" declaration (later on), but let's look at the begin...end block. You see that although p doesn't point to any variable, it can still be assigned with values. How can it be? Well, that's one of the tricks.

The statement new(p); does reserve space in memory. After reservation, you could do anything to that variable until you release the memory using dispose(p);.

So, what's the point? The point is that we could derive more memory with the cost of 4 bytes to static variable space. Remember that pointers are long integers, that eats 4 bytes. What we have reserved is not counted into static space, but to dynamic space. Thus, the created variables from pointers are called dynamic variables. The second reason why it is called dynamic is that we could reserve and dispose any time we want throughout our program.

One rule to keep is that you must ensure all reserved memory is released after use. Otherwise, you might bring a marvelous crash into your system. J That's the nightmare of the most programmers. One is revealed. J The solution is that don't forget to ensure each reservations ends with releases.

For those who unwillingly accept the "type" part of the above section, let's argue. For every pointer, regardless of its type, Pascal assigns 4 bytes to it. It is due to pointer variable is similar to long integers. So, whenever Pascal compiler encounters the caret sign, he assigns 4 bytes, not checking the words or so behind it. But, you must ensure the words behind it are defined afterwards, otherwise Pascal spits an error. The only thing Pascal would like to know is the memory assignments, and probably the code validity. That's all. I hope that it is clear enough for you. If you still don't understand, mail me.

 

Let's now learn generic pointers. Generic pointers are pointers with no specific data types. Usually, pointers are associated with specific data types, but generic pointers don't. How to declare generic pointer? It's simple:


Var
P : pointer;

What does it for? It is usually used as a temporary buffer. Remember the file copy in the first lesson? We used array as the buffer. Now I said that array as temporary buffer is considered obsolete and inefficient. Why? It is because array is a static variable, can not be removed in any way. The purpose is for temporary buffer, not permanent one. So, it is better for us to get rid of them after we used it so that we could make use the freed memory for other purposes. Therefore, it is better to use pointers because of their dynamic nature.

However, generic pointer assignment is not the same as typed pointer. Typed pointer uses "new" to reserve memory and "dispose" to release it. Now, it is different. Generic pointer uses "getmem" to reserve memory and – of course – "freemem" to release it.

When in typed pointer Pascal knows the size of the will-be-reserved-size of the memory, in generic pointer Pascal does not. Why? It is because Pascal doesn’t know what variable it is associated to since generic pointers need not be associated into one (I mean the types). So, in getmem, we need to specify the size of how many bytes we want to reserve in the memory. The largest size you can reserve is 65532 bytes (almost 64K). And you could assign as many as you want, until Pascal disallow you.

In "freemem" we use the same rule. We need to specify the size we want to free. Most programmers find it unnecessary to specify the memory size in freemem since most of us want to free all bytes that are reserved by that pointer. But, I think the original intention of the Pascal creators is that it enables us to adjust the size of the pointers. Most programmers think resizing is not necessary. Let's take a look at this example, a generic pointer in action:


Var
P : pointer;
Begin
Getmem(p,8192);  { Reserve 8192 bytes }
:
:                { We use it then }
freemem(p,8192); { Release it, 8192 bytes }
end.

How to use generic pointers. Look at this line:

Blockread(f, p^, 8192);

Means that we read 8192 bytes from file associated with f then put it into buffer p.

Got any ideas for the new file copy program? I hope so. J

OK, that's all for now. Shall we go to the quiz or the next lesson? Or you still don't understand? Mail me!


Where to go?

Back to main page
Back to Pascal Tutorial Lesson 2 contents
To the quiz
To Chapter 2 about single linked lists
My page of programming link
Contact me here


By: Roby Joehanes, © 1997, 2000