Vous êtes sur la page 1sur 31

CS1010 Lecture 7

Pointers
Henry Chia
hchia@comp.nus.edu.sg

Semester 1 2011 / 2012


Department of Computer Science
School Of Computing
National University Of Singapore

CS1010 Lecture 7 p.1/31

Lecture Outline
Memory addresses
Pointers
Declaration and assignment
Dereference
Pointer comparison
Pointers in functions
Pointer parameters
Address as return value
Pointers to structures

CS1010 Lecture 7 p.2/31

Memory Addresses
When a program is executed, memory
locations are assigned to the variables.
Each of these memory locations has a
positive integer address that uniquely defines
the location.
When a variable is assigned a value, this
value is stored in the corresponding memory
location.
The specific addresses used for the variables
are determined each time that the program is
executed and may vary from one execution to
another.
CS1010 Lecture 7 p.3/31

Memory Addresses
For the following declaration:
int count = 1010;

Detailed memory representation:


@100

count 1010

In the slides, a memory address value is


indicated with a @ sign.
Note: Addresses used for illustration are not representative
of the exact address allocation policy.

CS1010 Lecture 7 p.4/31

Address Operator
The address of a variable can be referenced using the
address operator &,
double x = 1.23;
printf("%lf stored at %p\n", x, &x);

Address may be printed with a %p placeholder.


Apart from debugging with printf, actual address
values are not used explicitly as they are system
dependent and may vary from one execution to
another.

CS1010 Lecture 7 p.5/31

Pointer Variable
The C language allows us to store the
address of a memory location in a special
type of variable called a pointer variable (or
simply pointer).
When a pointer is defined, the type of variable
to which it will point must also be defined.
Thus, a pointer defined to point to an integer
variable cannot also be used to point to a
floating-point variable.

CS1010 Lecture 7 p.6/31

Pointer Declaration
Consider the following declarations:
int count=1010, *ptr; // int count;
// int *ptr;

C uses an asterisk in declarations to indicate


that the variable is a pointer variable.
int *ptr is read from right to left as
declare ptr as a pointer to a int.
Identifier name is ptr; type is int *.
Although ptr can be initialized during
declaration, use separate assignment
statement to avoid notational confusion.
CS1010 Lecture 7 p.7/31

Pointer Declaration
The memory representation for the
declaration on the previous slide is as follows:
@100

<int> count 1010


@300

<int *> ptr

ptr stores an unknown address value;


however ptr is located at memory address
@300.

CS1010 Lecture 7 p.8/31

Pointer Assignment
To specify that ptr should refer (or point) to
the variable count, assign the address of
count (&count) to ptr:
ptr = &count;

The memory representation is as follows. To


avoid using memory address values, you may
use arrows to point to the desired variables.
@300

@100

<int> count

1010

<int *> ptr

@100

Is ptr = &ptr; valid?


CS1010 Lecture 7 p.9/31

Pointer Dereference
Consider the following statements:
int count, *ptr;
ptr = &count;
*ptr = 1020;
printf("Var at %p stores %d\n", ptr, *ptr);

The asterisk used in statements is a


dereferencing or indirection operator.
In the statement *ptr = 1020, assign 1020
to the variable pointed to by ptr, i.e.
variable count now stores the value 1020.
In the printf statement, *ptr is the value
pointed to by ptr, i.e. the value of count.
CS1010 Lecture 7 p.10/31

More Pointer Assignments


Now consider the following declarations:
int count = 1020, *ptr1, *ptr2;
@300

<int *> ptr1

?
@100

<int> count 1020


@400

<int *> ptr2

CS1010 Lecture 7 p.11/31

More Pointer Assignments


ptr1 = &count;
Assign the address of variable count to
the variable ptr1.
@300

<int *> ptr1 @100


@100

<int> count 1020


@400

<int *> ptr2

CS1010 Lecture 7 p.12/31

More Pointer Assignments


ptr2 = ptr1;
Assign value of ptr1 to variable ptr2.
A pointer can be assigned to another
pointer of the same type, i.e. several
pointers can point to the same location.
@300

<int *> ptr1 @100


@100

<int> count 1020


@400

<int *> ptr2 @100


CS1010 Lecture 7 p.13/31

Pointer Assignment Errors


To illustrate some common errors that can be made
when working with pointers, assume
int y, *ptr1, *ptr2;

Changing the address of an integer variable:


&y = ptr1;

Assigning pointer with a non-address value:


ptr1 = y;
ptr1 = *ptr2;

Assigning an address to an integer variable:


y = ptr2;
*ptr1 = ptr2;
CS1010 Lecture 7 p.14/31

Pointer Comparisons and NULL


Because different pointers can point to the
same variable, we use relational operators
== and != to compare pointers.
Other relational operators <, >, <=, >= more
relevant in the context of arrays.
A pointer can be assigned to or compared
with the constant NULL (which is the integer
zero) defined in <stdio.h>.
To zero a pointer, assign a NULL value to
indicate that the pointer has no address.
ptr = NULL;

// or ptr = 0;
CS1010 Lecture 7 p.15/31

Pointers as Function Parameters


Recall the pass-by-value function mechanism
where copies of values are passed down from
the caller function to the callee function.
Pass-by-address-value involves function
arguments being first evaluated to address
values before passing to function parameters
(or more specially, pointer parameters).
Nonetheless, it is still pass-by-value the
only argument passing mechanism.

CS1010 Lecture 7 p.16/31

Swapping Revisited
Consider the following swap function.
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
return;
}

Pass-By-Value: calling swap(x,y) does not


swap values of x and y of the caller function.

CS1010 Lecture 7 p.17/31

Swapping Revisited
int main(void)
{
int x = 5, y = 2;
swap(x,y);

void swap(int x, int y)


{
int temp;
temp = x;
x = y;
y = temp;
return;

return 0;
}
main
x

swap(x,y);

}
swap

2
temp

CS1010 Lecture 7 p.18/31

Pointers as Function Parameters


cf . swap function with pointer parameters:
void swap(int *ptrX, int *ptrY)
{
int temp;
temp = *ptrX;
*ptrX = *ptrY;
*ptrY = temp;
return;
}

If x and y are simple integer variables, then a


valid call to this function is swap(&x,&y);

CS1010 Lecture 7 p.19/31

Pointers as Function Parameters


int main(void)
{
int x = 5, y = 2;
swap(&x,&y);
return 0;
}
main

void swap(int *ptrX,


int *ptrY)
{
int temp;
temp = *ptrX;
*ptrX = *ptrY;
*ptrY = temp;
return;
}
swap

6
swap(&x,&y);


ptrX

ptrY

When an address is passed to a function, draw a reference from the function parameter to the specified location.
CS1010 Lecture 7 p.20/31

Pointers as Function Parameters


int main(void)
{
int x = 5, y = 2;
swap(&x,&y);
return 0;
}
main
x

6
swap(&x,&y);

void swap(int *ptrX,


int *ptrY)
{
int temp;
temp = *ptrX;
*ptrX = *ptrY;
*ptrY = temp;
return;
}
swap


-

ptrX
temp

ptrY
5

CS1010 Lecture 7 p.21/31

Pointers as Function Parameters


What happens in the following case?
void swap(int *ptrX, int *ptrY)
{
int *temp;
temp = ptrX;
ptrX = ptrY;
ptrY = temp;
return;
}

When using scanf, say scanf("%d", &x),


value read from the keyboard is stored at the
address specified by &x, the address of x.
CS1010 Lecture 7 p.22/31

Pointer Parameter as Function Output


With pointer parameters, one can use them to
return one or more values from a function.
Since these pointer parameters are used for
output from a function, they are termed output
parameters.
The function below finds the sum and product
of two arguments x and y.
void findSumProd(int x, int y,
int *sum, int *prod)
{
*sum = x + y;
*prod = x * y;
return;
}
CS1010 Lecture 7 p.23/31

Pointer Parameter as Function Output


The caller function calls findSumProd as
follows:
int main(void)
{
int a, b, sum, prod;
scanf("%d %d", &a, &b);
findSumProd(a,b,&sum,&prod);
printf("The sum and product of ");
printf("%d and %d are %d and %d.\n",
a, b, sum, prod);
return 0;
}

CS1010 Lecture 7 p.24/31

Address as Return Value


Returning an address from a function is
possible but seldom useful apart from
function compositions.
Consider the example of finding which of two
variables a and b is bigger and making that
value twice as large.
Function findBigger takes two addresses of
variables as arguments, determines which variable
holds a larger value, and returns the address of this
variable.
Function makeEvenBigger takes the above
address, finds the value, and multiples it by two.
CS1010 Lecture 7 p.25/31

Address as Return Value


int main(void)
{
int a, b;
scanf("%d %d", &a, &b);
makeEvenBigger(
findBigger(&a,&b));
return 0;
}

int *findBigger(int *a, int *b)


{
if (*a > *b)
return a;
else
return b;
}
void makeEvenBigger(int *c)
{
*c = *c * 2;
return;
}

Notice that functions need only communicate


the address values, and not the actual values.
Question to Ponder...
Suppose function f calls function g. Can we
return an address of a variable declared in
function g back to the caller function f ?
CS1010 Lecture 7 p.26/31

Pointers to Structures
Pointers variables can refer to structures.
struct Point
{
double x, y;
};

int main(void)
{
struct Point pt = {1,2},
*pPtr;
pPtr = &pt;
return 0;
}

pt

@500
1.0
2.0

@600

pPtr

@500

CS1010 Lecture 7 p.27/31

Structure Pointer Parameters


To allow the callee function direct access to
the data members of the structure in the
caller, pass a pointer to the structure as
function argument.
void getPoint(struct Point *p)
{
double x, y;
printf("Enter (x,y) values for point:\n");
scanf("%lf %lf", &x, &y);
(*p).x = x;
(*p).y = y;

// dereference then member access

// or.. scanf("%lf %lf", &((*p).x), &((*p).y));


}

Function call in main: getPoint(&pt);


CS1010 Lecture 7 p.28/31

Structure Pointer Parameters


As a shorthand to using (*p).x, the pointer
to structure member operator (->) can be
used instead, i.e. p->x.
void getPoint(struct Point *p)
{
double x, y;
printf("Enter (x,y) values for point: ");
scanf("%lf %lf", &(p->x), &(p->y));
}

Finding the midpoint of two points pt1 and


pt2 via output parameter midpt:
void midPoint(struct Point *pt1,
struct Point *pt2,
struct Point *midpt);
CS1010 Lecture 7 p.29/31

Structure Pointer Parameters


int main(void)
{
struct Point pt1, pt2, midpt;
getPoint(&pt1);
getPoint(&pt2);
midPoint(&pt1,&pt2,&midpt);
printf("Midpoint: (%lf,%lf)\n", midpt.x, midpt.y);
return 0;
}
void midPoint(struct Point *pt1, struct Point *pt2,
struct Point *midpt)
{
midpt->x = (pt1->x + pt2->x) / 2;
midpt->y = (pt1->y + pt2->y) / 2;
return;
}
CS1010 Lecture 7 p.30/31

Lecture Summary
If you are new to pointers, devise and use
memory addresses to assist in program
traces; then progress on to using arrows.
Ensure type-consistency when assigning
pointers.
Addresses are passed to functions via
pass-by-address-value, i.e. a copy of the
address is passed to the pointer function
parameter.
Addresses and pointer dereferencing apply to
both primitive variables as well as to structure
variables.
CS1010 Lecture 7 p.31/31

Vous aimerez peut-être aussi