| |
Main Menu | Next Section |
| Section II: Using Pointers | Section I: Memory Allocation and the Pointer | Section III: Arrays and Pointers | Section IV: Strings |
A. Assigning Values to Pointers
So we know that pointer variables hold memory addresses and that they
point to memory locations containing some specific type. Now,
how do we put the addresses into pointer variables? One thing
we don't do is:
This would be extremely dangerous if, it were allowed. It
would be saying you want to be able to access memory location
324 or, as we will see in a bit, be able to put a value into this
memory location. But, what if address 324 is part of the operating
system or part of your program. If you could change it, you would
be changing the code for the operating system or the program, and
it is most unlikely that the change would be for the better. So,
we are, in general, not allowed to choose which memory locations
we have direct access to. Instead, we ask the system to provide
us with memory that it knows is free. We can then do what we want
with that memory without worrying about possible bad effects.
C++ provides an instruction for making such a request. If you want to ask for enough memory for a double and store the address of that memory location in 'ptrDouble', you write:
If you want to ask for enough memory for a contract and store the address of that memory location in 'ptrContract' you write:
The same is true for any other pointer type.
Although 'new' was referred to above as an instruction, it really
is an operator - the same as '+', '-', etc. At this point, however,
that is not very important. What is important is what this 'new'
operator does. When the operator is called, two things happen:
Consider again the code:
When the 'new' operator is called here, the system allocates enough
memory for a double. Assume that the allocated memory begins with
the byte address 54,366. This value is then placed in the variable
'ptrDouble' and we get the usual picture:

Often, programmers do not include the type in variable names so
one might write:
or even:
This is legal, just as any other declaration/initialization is legal. What is not legal is, for example:
In this case, you are trying to put the address of an integer
into a variable that has been declared to hold a pointer to a
character. As we said above, a pointer variable can only hold
the address of the type it was declared to hold.
To request enough memory for an array of some type, a slightly
different form of the 'new' operator is used. Since the address
returned will point to the first byte of the array, the pointer
declaration remains the same. Thus, if you want a pointer to an
array of integers, you can declare your pointer as:
The change is that you must include the size of the array in the
'new' statement. Thus, if you want to request enough memory for
ten integers, you write:
To declare and assign a pointer to twenty contracts, one could
write:
There are two other ways to assign a value to a pointer. First, it is also legal to write:
This means that, for the moment, 'ptr1' points to nothing; it holds
the null pointer. (If the 'new' operator fails in its attempt
to allocate enough memory for whatever is to be pointed to, it
returns the null pointer.) Later, we will see a number of uses
for this null pointer value.
The third legal way to assign a value to a pointer is by assigning the value of one pointer variable to another - as long as they are both of the same type. Therefore, it is legal to write:
Now both 'ptr1' and ptr2' point to the same memory location.

This also can be quite useful as we will see.
B. Accessing Memory Via Pointers
The key to these memory address assignment rules is that we, as
programmers, do not have the ability to explicitly say that we
want to use memory location 'X'. However, once the system has
given us a memory location to use, we can trust that it is safe,
and we can pass that memory location on to other pointer variables
and use it for our own purposes. The next step is to learn how
to access the addresses (or memory locations) being pointed to
by variables.
In the code:
we first declare 'ptrInt1' to be a pointer to an integer and we can think of memory as looking as shown in figure 9.5. (The question mark inside the memory cell indicates that this memory location holds garbage.)

Then we ask
the system to provide enough memory to hold an integer and to
assign the address of the first byte of that memory to 'ptrInt1'. Now memory can be considered to have the form:

Note how the left memory cell now contains an address. The function 'new' set aside the memory with this address and returned this address, whereupon it was stored in 'ptrInt1'. This new memory (the memory cell on the right) has not had anything placed in it yet, so it holds garbage.
To store the value five into the memory made available, we would write:
This brings up the distinction between
The first acts like any other variable name and refers to the
memory symbolized by the variable 'intPtr1'. It, thus, refers to
the box labeled "ptrInt1" in figure 9.6, the box containing the address 54366. In contrast,
'*ptrInt1' refers to the address pointed to by the memory location
symbolized by 'ptrInt1'. In other words, '*ptrInt1' refers to
the second box in the figure.
When a system sees an asterisk followed by a variable declared to point to some type, it looks in the variable for an address and follows that address to a memory location. Therefore,
means "Go to the memory location symbolized by the variable 'ptrInt1' and get the address stored there. Then go to the memory location with that address and put the value five in it. After this code is executed, the picture changes to:

Now consider this code:
The semantics of the last line here are as follows:
When the instructions are finished, the 5 in the memory location pointed to by ptrInt1' has been added to the 4 and the result has been placed in the memory location pointed to by 'ptrInt2'. The results are shown in figure 9.8. Notice that in this figure the memory addresses are not included. This is the way these figures should be drawn, indicating that we do not know the actual memory locations used.

This process of 'following a pointer' to get to a memory location is called dereferencing the pointer and a dereferenced pointer can be used anywhere a variable can be used. For example, consider the following code:
We will see code similar to this in a bit. For the moment, just
remember that:
Topics Covered in the "Essentials of C++"
| |
Main Menu | Next Section |