Comp 11

Pointers

Review

Today: Pointers

Pointers in a nutshell

A pointer is a memory address.

They often look like this 0x7fff3889b4b4 or 0x60132, or 0x602010 (some examples taken from a program I just ran). These addresses are expressed as numbers in hexadecimal, which is base 16 (that's what the 0x at the beginning means). You don't have to know what the numbers are, but you do need to know that:

Example Problem: Sorting things that are too big to move

Suppose you had a bunch of large objects. E.g, stones weighing between 1 and 5 tons each of various sizes. Appartments in a building. Buildings on a street.

You want to order the stones by size to be used in the construction of a bridge/pyramid/something. The appartments should be sorted by the length of time they've been vacant, or the time since they were last painted. The buildings should be sorted by excise tax value, square footage, number of residents.

How would you do that? Would you rearrange the buildings on the street? No.

You'd give each item a name, a reference, and you'd sort those.

Exercise:
Draw a picture of buildings on a street and write a bunch of random values for the their square footage.

Choose a representation for references to the buildings. Make an array and sort them. How do you use the references during the sorting procedure?

Indirection in arrays

Imagine an array of large structures. Maybe a struct in this case represents all the information about a student at Tufts. Can you use the technique above?

Draw out the array and a parallel array of …

Pointers in C++

C and C++ allow you to manipulate pointers explicitly.

Discussion and questions.

Exercise:
Read and understand pointer_example1.cpp. Run it!

Warning:
There is considerable confusion out there about the * symbol. It is not part of the type, though people often pronounce it, and even worse, write it that way. A declaration has a type followed by variables in sample expressions that would produce a value of that type.
int  *p, x;  // declares a pointer to an int and an int
int*  q, y;  // SAME!!  EVIL EVIL EVIL — NEVER WRITE THIS!!
	
Some will call the second example above a difference in style — it isn't. It's an abomination! I have seen experienced programmers waste hours because of it. The * goes with the variable, not the type, so write it there! (My theory is that it's a habit picked up when the person didn't understand what was going on, and when/if they did figure it out, they continued it out of a perverse notion of style and as a way to haze newcomers.)

Warnings/Common Bugs

A fun video

Play this AVI video. It uses evil declarations, but it's otherwise fun.

Summary

How to pass a structure or object cheaply (by reference)

Now you know exactly what C++ does with arrays!

See pointer_example3.cpp.

Of course the same holds for classes, because classes are structs. So, you can pass an instance of a class by reference just as you we passed an instance of a struct by reference above. Change the word struct to class, and the example is exactly the same!

Whenever you are are exectuting a member function of a class, there is always a pointer to the instance from which the function was selected available. Its name is this. For example, inside Kangaroo::put_in_pouch(), there is a variable this that is a pointer to a Kangaroo, as if it had been declared
Kangaroo *this;
        
In fact, this is really an unwritten parameter of every member function. When put_in_pouch() refers to pouch_contents, it's really referring to this->pouch_contents, and you can refer to it using that same notation if you like. This leads to a common idiom in constructors in which parameters that are used to initialize member variables have the same names as the variables:
MyClass::MyClass(int a, double b, Kitten k)
{
        this->a = a;
        this->b = b;
        this->k = k;
}
          
Of course, you would never pick such awful parameter and data member names!

Simple call-by-reference variables

Call by reference can be useful for ordinary variables, too. Usually, one does this when a function would like to return more than one value. In C/C++, one does this by returning a struct, which can seem like a lot of trouble for a small special case, or by using call-by-reference parameters. C++ has two mechanisms for doing this. Here's how you do it with pointers.

cbr_demo.cpp

The code above uses a read_string() function to get a string, but it also returns true if it succeeded and false otherwise. We could have defined a struct that could hold a boolean and a string, but, in this case, we returned the success/failure indication using normal function return, and returned the string we read (if we read one) by placing it directly in the caller's variable.

A function cannot access another function's variables directly by name. However, a function may pass the address of one of its variables as a pointer parameter. Inside read_string(), s is a pointer to the caller's string variable, in this case it's the address of main()'s variable word. Thus, *s in read_string() is the same variable (the same location in memory) as word in main(). Therefore, assigning to *s is the same as an assignment to word.

Dynamically Allocated Variables/Arrays

Problem: How can we (portably) write a program that makes an array of a size that is determined at run time? How can we make that array survive beyond the completion of the function that created it? Maybe the size is read in from the keyboard or gotten from a web form; maybe you need to do an involved computation to figure out how much space you need, for example, in a weather simulation or in the graphics for a video game.

First, creating and destroying variables dynamically:

See new1.cpp.

Creating and destroying arrays dynamcially:

Examples:

Putting it all together for dynamic arrays

Suppose you have a 1-drawer file cabinet in your room for all your course notes, financial documents, etc. Eventually, you take lots of courses and it fills up. What do you do?

We're going to make a growable array abstraction that works the same way. It will start out small and then grow as needed.

Debugging

Mark A. Sheldon (msheldon@cs.tufts.edu)
Last Modified 2017-Sep-07