| |
Main Menu | Next Section |
| Section I: Memory Allocation and the Pointer | Section II: Using Pointers | Section III: Arrays and Pointers | Section IV: Strings |
A. Static and Dynamic Memory
In the last chapter we explored one way to implement a list -
using arrays embedded inside a class structure. The basis of this approach was that one could use as little or as much
of the array as one wanted - depending on the size of the list.
But, what happens when the array fills up? In the case of the
contract list, what happens when there are more than MAX_CONTRACTS
contracts? If you recall, the code was written to output a warning
message saying that it was not possible to add another contract.
Notice that the code outputs a 'fail' message, not when there is no more memory in the system, but when the memory set aside for the array is used up. Now we could always make the array huge, as big as RAM memory will allow, so it would be very unlikely that there would be too many contracts. However, consider a slightly more complex example. We have ten different kinds of contracts, each requiring its own list. And, we have no idea which of the lists will be large and which will be small. We can't make the arrays for all the lists huge, there is not enough memory. We are left with the ugly choice of guessing which lists will be huge and hoping we are right, or making the lists all the same size and potentially winding up in the ridiculous situation of having one list be practically empty while another is full and unable to take more contracts.
Be sure you understand the reason for this: when the program first
begins, memory is set aside for each array - long before the program
knows how big each array needs to be. And, once the program starts,
there is no way to change the amount of memory allocated for any
given array, unless one stops the program, changes the code, recompiles
it, and starts again! This is an example of what we call static
memory allocation, 'static' because the amount of memory allocated cannot change while the program is running.
In this chapter we are about to learn about a new kind of memory
allocation - dynamic memory allocation. Using this, a program
is able to request memory from the operating system as it needs
it - up to the maximum amount of memory in the system. To handle
the above situation, the program would start by allocating a small
to medium size amount of memory for each list and then as any
particular array filled up, it would ask for more memory JUST
for that list. If the program was sophisticated enough, it might
even look for lists that had extra room and allocate less space
for them once the system as a whole ran out of memory.
B. The Pointer
To accomplish this, we need to introduce a new concept - the pointer.
Remember each memory location has a unique address and that
variables are really symbolic names for these memory addresses.
A pointer is a memory location that contains the actual address
of some other memory location, instead of containing an integer,
a double, a character or the beginnings of some user-defined type
A picture might help:

Here we see two boxes representing memory locations. The box on
the left, with the symbolic (variable) name 'ptrVar', contains
what looks like a large integer. This integer is actually the
address of the memory location represented by the second box.
The arrow between the two boxes represents the idea that the address
in the left hand box 'points to' the box/memory location on the
right.
If we had two arrays, each pointed to by a pointer, we might have
the following picture

This time, each memory location on the left points to the first
memory location of an array with each array being of a different
size.
Note that in both these figures, there is no variable name associated
with the boxes on the right. The only way one gets to these memory
locations is by 'following' the addresses (pointers) in the memory
locations on the left. The memory locations on the left do have
variable names associated with them and would be accessible to
a program, if that program correctly declared the variables. We
will see how to do so in a bit.
C. Declaring a Pointer
OK, so now you understand this at the conceptual level. It is
time to get down to the details. As usual, we will start with
a simpler goal - simply declaring pointers to some of the built-in
types. Frankly, there is little value in doing so, but it is easier
if we start this way, and it is always nice to begin slow and easy.
We know what
means to the computer - "set aside enough memory for an integer
and give that memory the symbolic name 'x' ." We also know
that this memory location initially contains garbage.
Above, we saw that a value that might look like an integer is interpreted differently if it is declared as a pointer. To declare a variable that is to hold a pointer to an integer, we write:
The '*' is the new part. What this means to the computer is, "Set
aside enough memory for a pointer to an integer and give
that memory the symbolic name 'ptr'." In other words, whenever
the system works with 'ptr', it knows that the contents of 'ptr'
is not simply an integer but is an integer acting as a memory
address.
One important point in C++ is that pointers point to a memory
location holding a value of some specific type. Consider these
declarations:
int* ptrInteger; 'ptrInteger' holds the address of a
memory location containing an integer;
double* ptrDouble; 'ptrDouble' holds the address of a
memory location containing a double;
char* ptrChar; 'ptrChar' holds the address of a
memory location containing a character;
Contract* ptrCont; 'ptrCont' holds the address of a
memory location containing a contract;
This means, for example, that 'ptrInteger' can NOT point to a
memory location containing a double.
In chapter two we said that each type takes up its own
amount of memory. Thus characters might take up one byte, integers
two bytes, doubles four bytes. The amount of memory required by
a contract is a bit more complex, but it takes up at least the
amount required for each of the individual data members in a contract.
And, an array of 20 contracts will take up 20 times the memory
required for one contract.
The point (a pun?) of this is that, when it says above that some
variable "holds the address of a memory location containing
a ...", what it really means is that the variable holds the
address of the first byte of the memory used for whatever type
is being pointed to. That is one reason why a variable acting
as a pointer must point to a specific type. The system needs to
know how many bytes to handle as part of the data being pointed
to.
| |
Main Menu | Next Section |