Lecture #21: Pointers

November 22, 1999

Bob Pitha

bpitha@cs.ucsd.edu

http://www-cse.ucsd.edu/classes/fa99/cse5a

the nature of memory

•      Way back, we talked about computer memory

–   it’s a bunch of bytes

–   each byte can hold 256 values

–   “adjacent” bytes can be combined to hold larger values

•   usually grouped in powers of 2 (2, 4, 8, 16, …)

•      What’s “adjacent” mean?

–   bytes in memory are numbered sequentially

sequential numbering

•      So memory is a long sequence of storage spaces for numbers

–   like a long line of lockers

–   each locker is given a number

–   C lets us use that number…

addresses

•      In C, we call these “locker numbers” addresses

–   an address is the number of the byte we want

•   or if we’re talking about a grouped byte, it’s the first byte of the group

•      When a variable contains an address, we call it a pointer

–   because it “points” to some other data in memory

it’s like a treasure hunt…

•      Up to now, we’ve dealt only with straightforward variables

–   they hold the data we care about

–   just like a locker holding something for me

•   I can put my book in my locker and get it again later

•      Pointers introduce a level of indirection

–   instead of holding the data, they hold information about where to find the data

–   so now my locker would only hold a piece of paper, telling me which locker to look in for my book

what’s the point?

•      Indirection can be helpful

–   when the actual data location may change

•      Analogy: the cs5a@ieng9.ucsd.edu e-mail address

–   mail sent to this address goes to me

–   but next term, if someone else is teaching CSE 5a, it will go to that person

just more numbers

•      Like every other kind of data we use, addresses are numbers

–   up to now, though, our data has been numbers we care about

•   temperatures

•   dates

•   results of calculations

–   addresses are numbers too, but ones that only are useful to the program while it’s running

data types

•      A pointer isn’t a new data type

–   it’s just kind of a modification, because the pointer should point to a data type

•   or another pointer, that must eventually find a data type

declaring a pointer

•      We declare a pointer using a *

–   this declaration creates a variable named ptr

Text Box: int *ptr;
 


•   ptr is a variable whose value is an address

•   the thing we expect to find at that address is an int

•   since an int is 4 bytes (on our computers, at least), this is the address of the first byte of a group of 4 bytes

–   but ptr has not yet had its value set, so it does not yet contain a valid address of anything

the address-of (&) operator

•      The unary operator & is used to find an object’s address

–   that is, its operand is an object

•   remember that an object is something with memory associated with it

–   the value of the expression (operator and operand) is the address in memory of the operand

example

•      So, let’s put this all together:

Text Box: int i = 1;
int *ptr = &i;
 


–   the first line defines a variable named i

•   it is an int, and thus has 4 bytes of memory reserved for it

•   its value is set to 1

example

•      So, let’s put this all together:

Text Box: int i = 1;
int *ptr = &i;

 


–   the second line defines a variable named ptr

•   it is a pointer to an int

•   it is initialized to the address of i

–   thus, it contains a number which is an address
–   if you look at the 4 bytes starting at that address, you will find the value 1

the contents-of (*) operator

•      The unary operator * is used to access whatever is at a given address

–   its operand is an address

–   the value of the expression is an lvalue

•   remember that an lvalue is an expression that refers to an object

•   and an object is something with memory associated with it

•   an address is supposed to refer to a location in memory

•   so an expression using the * operator refers to an object, and thus is an lvalue

–   that means we can assign its value as well as look at it

example

•      What does this print?


 


example

•      What does this print?


 


–   we know the first two lines create the variables i and ptr

•   i is an int, containing the value 1

•   ptr is a pointer, containing the address of i

example

•      What does this print?


 


–   *ptr refers to the thing that ptr points to

–   ptr points to the memory that stores the value of i

–   so this line assigns the value 2 to i

example


 


•      What does this print?

–   it just prints the value of i

–   which is now 2

confusion

•      This is going to be confusing for a while

•      We have 2 values now:

–   the value of the pointer

•   which determines what the pointer points to

–   and the value in the location the pointer points to

confusion

•      We can change the value of the pointer:

example

Text Box: int i = 42;
int j = 17;
int *ptr = &i;

*ptr = 1;
ptr = &j;
*ptr = 2;
 


•      What does this do?

 

example

•      What does this do?

Text Box: int i = 42;
int j = 17;
int *ptr = &i;

*ptr = 1;
ptr = &j;
*ptr = 2;
 


–   this declaration creates the variable i

•   i is an int, containing the value 42

example

•      What does this do?

Text Box: int i = 42;
int j = 17;
int *ptr = &i;

*ptr = 1;
ptr = &j;
*ptr = 2;
 


–   this declaration creates the variable j

•   j is an int, containing the value 17

example

•      What does this do?

Text Box: int i = 42;
int j = 17;
int *ptr = &i;

*ptr = 1;
ptr = &j;
*ptr = 2;
 


–   this declaration creates the variable ptr

•   ptr is a pointer

•   initially, it points to i

example

•      What does this do?

Text Box: int i = 42;
int j = 17;
int *ptr = &i;

*ptr = 1;
ptr = &j;
*ptr = 2;
 


–   this statement assigns the value 1 to whatever ptr points to

•   which, as we already know, is i

example

•      What does this do?

Text Box: int i = 42;
int j = 17;
int *ptr = &i;

*ptr = 1;
ptr = &j;
*ptr = 2;
 


–   this statement reassigns the value of ptr

•   so it now points to j instead of i

example

•      What does this do?

Text Box: int i = 42;
int j = 17;
int *ptr = &i;

*ptr = 1;
ptr = &j;
*ptr = 2;
 


–   and finally, we assign the value 2 to whatever ptr points to

•   which is now j

operations on pointers

•      What we’ve seen so far:

–   assignment (=)

–   dereferencing (*)

–   address (&)

pointer assignment

•      As with arithmetic assignment:

–   the object on the left side must be an lvalue

–   therefore, this is not valid:

Text Box: &j = &i
 


•      Both operands must be pointers to the same data type

–   valid:

Text Box: int i;
int *ptr = &i;
 


–   invalid

Text Box: double d;
int *ptr = &d;
 


pointer dereferencing

•      Single operand, must be a pointer

•      The data type of the expression is the data type of whatever the pointer points to

–   thus, given this declaration,

Text Box: int *ptr;
 


–   the data type of the expression *ptr is int

address-of operator (&)

•      Operand must be something with memory associated

–   so the expression &(i+j) is invalid

•      The data type of the expression is “pointer to T”

–   where T is whatever the data type of the operand is