Lecture #22: More Pointers
November
24, 1999
Bob
Pitha
remember…
• Pointers
give us a way of referring directly to a location in memory
• We
can declare a pointer variable:
int *p;
– but it
doesn’t actually “point” to anything until we set its value to a real address
• We
can find the address of a variable
– using the
& operator
int i;
int *p = &i;
remember…
• We
can operate on what a pointer points to
– using the *
operator
int i;
int *p = &i;
*p = 3;
– this sets
the value of i to 3
NULL
• There
is a special value for pointers, named NULL
– this is the
canonical “invalid” value
• it’s never a
valid address
• it can be
used to indicate when a pointer variable is not set to an address
• it’s useful
for initializing pointer variables before you’ve actually set their value
• it’s used in
a lot of other situations too, we’ll encounter some
– don’t
confuse this with the nul character, which is the name for ASCII code 0
• also ‘\0’
pointers and function arguments
• When
I introduced functions, I said that functions can have any number of inputs
(arguments), and a single output (return value)
– I lied.
Well, sort of…
how did I lie?
• In
C, arguments are passed by value
– this means
that when you specify an expression as an argument to a function call, the
value of that expression is copied into the parameter in the function
• remember, a
variable name is a simple expression
– so when we
change the value of a function parameter, we’re changing a copy, and the change
doesn’t affect the variable used to call the function
example
• Changes
to parameters don’t “pass back”

but…
• What
if the variable we pass into a function is a pointer?
– we still
can’t change the parameter inside the function and expect the change to affect
anything outside the function
– but we can
change the thing the pointer points to
• and then
when we return from the function, we can find the change at the same location
example

example – what’s going on here?


example – what’s going on here?


example – what’s going on here?


example – what’s going on here?


example – what’s going on here?


example – what’s going on here?


example – what’s going on here?


example – what’s going on here?


example – what’s going on here?


so what does all that mean?
• You
can “return” more values from a function than just the return value
– by passing
in pointers to other variables
– the function
can then use the pointer to change the value of the variable
scope
• This
circumvents the “scope” rules we talked about earlier
– remember
that a variable’s scope determines where it can be seen from within the program
– so in our
example, i and j were not in the scope of the function swap(), but we changed
their values anyway
extent
• There
is another variable concept called extent, that we haven’t really talked about
• Extent
determines how long the variable exists while the program is running
– scope is a
static property: it applies to the code
– extent is a
dynamic property: it applies to the running program
• Extent
and scope are often mixed together, but they’re really separate concepts
extent
• Let’s
look at our swap function again

– notice that
the variable tmp
is declared at the beginning of this function
• thus, its
scope is the entire body of the function
• and the
scope rules say that we can only use the name tmp within the function
scope vs. extent
• But
we just saw an example where we manipulated variable values from outside their
scope
– so in that
case, the variables still existed somewhere in memory
– scope says
whether we can use the name, not whether the variable will exist or not
variable lifetime
• But
each variable has a well-defined lifetime
– at some
point, the computer sets aside the memory for that variable
• before that
point, the variable doesn’t exist
– at some
later point, the compter frees the memory for that variable, so it can be used
for something else
• after that
point, the variable doesn’t exist either
• and if we
still have a pointer to that memory, it’s no longer valid
• to use that
locker analogy, it would be like someone still having a slip of paper with my
locker number on it, even though I’ve graduated and my locker’s been given to
someone else
variable extent
• The
lifetime of the variable is its extent
– most of the
variables we’ve seen and used so far have automatic
extent
• that means
they’re created and destroyed automatically, as needed
• each type of
scope has its own extent rules
• and we can
manually affect the extent of some variables
swap() again

•
In swap(),
we declare the variable tmp
– and it’s a
definition: it reserves some memory
– but up to
now, we haven’t looked at when that memory is reserved, and when it’s released.
extent of tmp
• The
extent of tmp
in this case pretty much mirrors its scope
– it’s created
when we enter the function
– it’s
destroyed when we leave the function
– that means
that every time we call the function, the expression &tmp may have a different
value
extent of i and j

• Similarly,
i and j exist from the
beginning of the block in which they’re declared until we leave it
– which is
really from the beginning of the program until it ends
– so they
exist while swap()
is being called
so what?
• Why
do we care about extent?
– What if we
did something like this?

returning a pointer

• Now
we’re returning a pointer
– (don’t ask
why; this is a contrived example)
– but product’s extent
ends at the return statement
– so this
function always returns an invalid pointer