Lab 09: Excercises related to pointers


This week's lab session will primarily be on Session 10 in the Lab Book, Pointers. You'll also also use the debugger xxgdb in this exercise to make sure you understand the relationships between pointers, addresses and data values.

You learned the basics of pointers in the C course (like COP2212) you took in a previous term. You may have seen them again this term in COT3002 this term, but this lab may happen before that lecture. You only need to know the basics of pointers for this lab, and here are three ways you can look over info on what you need to know:

If you didn't get a chance to look over one of these before lab started, don't try to read all of these now. Have a look at the five slides and Lab Book, and then ask your TA or read Astrachan later if you have questions.

Pointers will be very important as you implement dynamic data structures such as linked lists. This topic is only introduced in COT3002, but you will be using pointers a lot in your next course, COP3530, Data Structures. For more information on pointers, read section 12.1 in the Tapestry textbook by Astrachan.


Exercises: Session 10 in the Lab Book

Do these exercises in the lab and turn them in. Remember to type your answers into a file and e-mail the file to your TA (not to the faculty coordinator). Do all steps in each experiment unless noted.

Remember, when the lab-book mentions a program, say, CP10E03, don't type it in! Copy it to your current directory:
cp ~cot3002l/src/CP10E03.cpp .
This means the C files are in the subdirectory named 'src' in the directory of the user-name 'cot3002l' (note that's an 'ell' at the end, not a one!) Don't forget the final '.' after the name of the C file. (This means the target of the copy command is the current directory, and just use the same name as in the source directory.)

Note: If you run into a problem where you try to print a pointer variable to see what address it holds, and instead you see the value stored at that address, see this note at the end of this lab. We think this problem was due to an earlier version of g++/gdb but you may run into it again. But hopefully you won't have to worry about this at all.


Do the following experiments:

Remember the command to compile your program is:
g++ -g -Wall prog_name.cpp
Always use the -Wall option with g++ to show all warnings, some of which might be errors. You could also use the -o option to rename the output file to be something other than a.out


Comment for Experiment 10.2

Never forget the following important rule when using pointers:
Before de-referencing a pointer (in C or C++ by preceding it with *), you MUST make sure it is pointing to (in other words, contains the address of) memory that has been allocated separately. Such memory is allocated by

Be sure to learn this! If you don't, you'll spend hours trying to fix your mistakes. (Especially in COP3530, your next course using C++ programming. We are not kidding about this!)

To understand the error in the first of these two programs, ask yourself: we've declared the pointer, but what have we made it point to?  Anything? (If not, it has some random address in it with garbage (perhaps) stored there.  Who knows?)

Ask the same question about the second program. You may not see a run-time failure, but if p points to some random location and we store data there, this can't be good, can it?  We may be clobbering some important piece of info, or trying to access memory we do not have permission to access.  (This is the meaning of the infamous C/C++ errors message, "segmentation violation" and "bus error".)


Comment for Experiment 10.4

Because we are printing addresses in hexadecimal format (base 16), you need to remember or learn how to add numbers in hex instead of the decimal form (i.e. base 10) that we normally use. It's easy. If we have 16 digits, then 0-9 are not enough!  Thus we need a few more digits, so let's let A=10, B=11, C=12, D=13, E=14, and F=15. Here are some examples of adding numbers in base 16:

Which reminds us of a computer science joke!  (Come on! You love these, don't you?)
Question: Why can't computer science geeks tell the difference between Halloween and Christmas?
Answer: Because Oct.31 = Dec. 25.
Hint: What's 31 in octal (base 8)?

Back to serious stuff. As Step 3 explains, addresses are in terms of bytes (or 8 bits). It normally takes more than one byte to contain a number like an int or a double or float or a pointer.  (Ever hear people talk about 16-bit versus 32-bit operating systems?  Like DOS vs. Windows 98? 64-bit operating systems are coming someday soon.)


Experiment 10.8, not in the lab book.

Here is one additional experiment with 5 steps that uses the debugger to help you understand more about arrays and pointers, and also about run-time errors. Copy and compile the program CP10E08 using the -g option, then run xxgdb on the executable file. (You'll want to use your editor to study this program before you run, it of course.  See if you can see the problems before you run it.)

Step 1.
Run the program. Question: What run-time errors do you see in the output? (You'll have to look at the code to see what it's supposed to do, or what we might think it's supposed to do.)
Step 2.
Set a breakpoint at the first cout in the main function and run the program again. Use the debugger to find the addresses of the follow variables:
i array_A array_B pi str
Answer this: Write down these variables and their addresses in memory.

To print the address of a scalar variable like pi, type the debugger command print/u p
To print the address of an array variable like array_A, type the debugger command print/u &array_A[0] which prints the address of the first value in the array, which is the starting address of the array.

Step 3.
Now set a breakpoint at the for statement in the function fun, and then continue the program. Look at the message printed in the bottom window when the function stops at your breakpoint. It prints values associated with the 3 arguments being passed to function fun. (You also see these whenever you press the "stack" button or type "bt".)
Question: What is the meaning of are the values printed for the 2nd and 3rd arguments? (Answer in terms of what was passed to the function as arguments.)
Next, use the xxgdb print/u command to print the values of &ival ip &z[0] (Note the address operator for two of these.)
Question: Are these the same as any of the variables declared in main? Explain. (See your answers for Step 2.)
Step 4.
In C and C++ when you declare an array, you are allocating consecutive blocks of storage at a starting address. When we reference the first item (with index 0) we are getting the data stored at the beginning position of the array.
Question: when we use reference the name of the array (without any indexing), what does this really mean? (In your answer, use words like "value" or "address" when you need to.)
Step 5.
Explain in detail what causes run-time error using your answers to Step 2.

This is the end of the lab exercises you must do. Two informational notes follow. Look them over if you have time.


Information Item. Printing Addresses in C instead of C++:

If you were using C and not C++, you could use printf to print addresses and pointers. But you should not use the format specification %d with printf . Instead use %u to print pointers or address values as unsigned integers. Without this, memory addresses often print as negative numbers. (Why? Think about it.) However, if you do this in C, you'll see a compiler warning (if you use the -Wall option to gcc, which you always should) since we're converting from a pointer to a unsigned integer without using a cast to convert the types. This is a harmless type mismatch. (Harmless for these programs; maybe not always.)

C often provides a %p specifier for printf which should really be used for pointers and address. This does in fact work with gcc and prints address values in hexadecimal. (And no warning message about type mismatches.)  We are telling you this because you may need to use what you learn in this lab later when you might once again be writing C programs.  Also, the debugger xxgdb has an output format specifier that's a little like C's.


Having problems printing values of addresses? How to fix this:

If you could print addresses in the above exercises, skip this note.

With an earlier version of g++ and gdb, we had to alter the C++ code so that when we print address values they really do print like we want them to. The code as printed in the lab book didn't do what it should have; the pointers are dereferenced by the << operator, and we print the value of the item being pointer to instead of the pointer's value (i.e. a memory address). If you see this same problem, modify the programs by adding a C++ cast as described below.

To make this code work, when we want to output an address value to cout, we'll cast it to a special type, void *, which is often referred to as "pointer to type void". This is a special type of pointer called a generic pointer that is used frequently in C; we use them to point to data items of different types or even unspecified types. They can point to anything, where normally we specify the type of data value a pointer is allowed to reference (e.g. int *, which can only point to integers). So, don't be surprised to see the code on the computer use static_cast<void *> a lot when you don't see that in the book.  (Note: we only do this when we are printing an address.)  C++ knows that this type is a pointer, so it prints the value as a hexadecimal number, which is a good way to read addresses (which are large positive numbers).


Last modified 10/31/00.