CS 16, Winter 2018

Lab07:
C++ Pointers


Goals for this lab

By the time you have completed this lab, you should be able to

Step by Step Instructions

Step 1: Get together with your lab partner, and create a lab07 directory

Choose who will be the first pilot, based on an attempt to maximize this lab's learning potential for both of you. If your assigned partner is more than 5 minutes late, ask the TA to pair you with someone else for this week.

This lab's first pilot should log in, create ~/cs16/lab07/ and make that your current directory.

Step 2: Practice using pointers at the ch prompt

Start ch. Then declare i as int, ip as pointer to int, d as a double array of size 3, and dp as pointer to double. Do not intitialize any of them:

ch> int i, *ip;
ch> double d[3], *dp;

Assign the address of i to ip. Then assign the address of the first element of d (i.e., the name d itself) to dp. And finally, use the ch stackvar command to find out the "state" of your memory area so far (don't worry if your values of ip and dp differ from this example):

ch> ip = &i;
0x9f0f49c
ch> dp = d;
0x9f14770
ch> stackvar
    i                   0
    ip                  0x9f0f49c
    d (C array)
0.0000 0.0000 0.0000
    dp                  0x9f14770

Next set the value of i by using ip, and set the values of d using dp. Type all of the following assignment statements, and then use stackvar to verify i and d are set:

ch> *ip = 17;
17
ch> *dp = 1.25;
1.2500
ch> *(dp+1) = 2.5;  // notice pointer arithmetic
2.5000
ch> dp[2] = 3.75;   // notice pointer used like array name
3.7500
ch> stackvar
    i                   17
    ip                  0x9f0f49c
    d (C array)
1.2500 2.5000 3.7500
    dp                  0x9f14770

You might be wondering what good are pointers if you already have a variable name you can use more easily. And you are right to wonder about that, because these simple examples are just for instruction, and do not have any programming value in practice. However, there are things we only do with pointers. In later parts of this lab you will learn some ways they are useful as function parameters, but first learn about how pointers can be used to access dynamically allocated memory.

The C++ operator new dynamically allocates new memory - outside of your program's static memory space - and returns a pointer to the first byte in a consecutive block of memory that is large enough to hold the type we request. So for example, the following statement acquires enough new memory to store a double value, and saves the pointer to it in dp:

ch> dp = new double;
0x8e0a890

Even better, you can allocate lots of space dynamically, and use the returned pointer as if it were the name of an array! Always free dynamically allocated memory when you are done with it using the delete operator. Here we do that for the memory we just allocated, and then we get new memory large enough to hold 10 doubles:

ch> delete dp;
ch> dp = new double[10];
0x8e0aeb0

Now perform the following steps in order:

    Beware: sometimes ch will not behave properly when new or delete are used - yes, it seems that ch has a bug. If ch responds to the following code by continuously looping error messages, then close the terminal window. One time you might try to reopen the terminal, restart ch, and retry this lab step - but if it still doesn't work, then skip to Step 3 below. Good luck!

  1. If you did not already do it, use new to allocate enough new memory to store 10 doubles, and store the pointer in dp.
  2. Set the value at *dp to 10.0.
  3. Declare a new variable named p that is a pointer to double. Then type the following for loop, but replace CENSORED with an expression that sets the value at *p to 10 times the value at *(p-1):
    ch> double *p;
    ch> for (p = dp+1; p < dp+10; p++) *p = CENSORED;

Before going to Step 3, make sure you succeeded by typing the following loop and verifying your results match:

ch> for (p = dp; p < dp+10; p++) cout << *p << endl;
10.0000
100.0000
1000.0000
10000.0000
100000.0000
1000000.0000
10000000.0000
100000000.0000
1000000000.0000
10000000000.0000

Free the dynamically allocated memory before proceeding to Step 3, but be careful to include the [], because dp now points to an array:

ch> delete [] dp;

Step 3: Fix and test a function to swap two values

First: switch roles between pilot and navigator if you did not already do that.

Download a copy of this useless version of a function that tries to swap two integers, intswap.chf, and store it by that name in your lab07 directory.

Read the function, and see how it successfully swaps the values stored in a and b: when done, a is set to the value b used to be, and b is set to the old value of a. But then try to use it. Start ch (if necessary), create two integer variables named anything you want (our example uses a and b only to emphasize a point), pass these two variables to intswap, and then type their names to let ch display their resulting values:

ch> int a = 17, b = -4;
ch> intswap(a, b);
ch> a
17
ch> b
-4

Oops. It doesn't work. That's because it processed copies of the variables passed to it, and so it was not able to change the values of the original variables. C++ has reference variables that let you change the values of arguments passed to functions, but in the C language it is only possible to do that if the function has pointers to the original variables. We want you to rewrite the function to operate on pointers, and it means the addresses of the two variables must be passed to the function when we use it. Here are the steps to take and the results to expect:

ch> emacs intswap.chf
ch> remvar intswap
ch> intswap(&a, &b);
ch> a
-4
ch> b
17

Things to notice: (1) ch's remvar command is used to remove the old version of intswap from memory, so ch will load the edited version when it is used - this step means we don't have to exit ch to use the newer version; (2) addresses of a and b are passed to intswap; and (3) it works now!

Open intswap.chf in an editor, and make the following changes:

  1. Type your name(s) and the date in the comment at the top.
  2. Revise the function header so a and b are declared as pointers to int.
  3. Revise the three statements, so a and b are used as the pointers they are now - dereference them to access the memory at which they point. Do not change the type of temp though: it should temporarily store a value, not an address.

Save the file and exit the editor. Then test the function with ch (after removing the previous version if you did not exit ch yet).

Beware "segmentation faults" that might shut down ch. Read the error messages, and try to fix the problem before asking a TA for help. Also, when you're done with this lab, use rm to delete any files beginning with "core" that might have been created in your current directory.

Exit ch when you are done testing the function. We will use swaptest.cpp to test it when you submit (notice it #includes "intswap.chf" to do that) - read it to know how useful your function is.

Step 4: Submit your completed function

If you are still logged on, and your current directory is still the same as your function, then the quickest way to submit is by entering the following command (suggest you copy/paste):

~submit/submit -p 965 intswap.chf
Otherwise you can use the submit.cs interface at https://submit.cs.ucsb.edu/ from your web browser - submit intswap.chf for Lab07. A perfect score is 50/50 points.

If you are working with a partner, be sure that both partners' names are in a comment at the top of the source code file, and be sure to properly form a group for this project in the submit.cs system.


Evaluation and Grading

Each student must accomplish the following to earn full credit [50 total points] for this lab:

If you finish before the end of your lab period, work on the optional challenges below.


Optional Extra Challenge


Prepared by Michael Costanzo.