You are on page 1of 54

Pointers

Week 3-5
What is a POINTER?
A pointer is a special variable; it is
special because it can only contain as
its value a memory address of
another variable.

A pointer provides an indirect way to
access the value stored in the memory
location where it points.
Mark De Vera
The Syntax

<data type> *<pointer name>

Example:
char *pch;
int *pi;
int *ptemp1, *ptemp2;
float *px;
double *pd;
Mark De Vera
The Memory Address of a
Variable

Use the ‘address of’ operator which is
denoted by the ampersand (&)
character.

Mark De Vera
Example:
Assume the following declarations:
int i;
int *pi;
int *ptemp;
float f;
float *pf;

Mark De Vera
Example…
 The following statement gets the address of i 
and stores it as the value of the pointer
variable pi.
– pi = &i;  /* pi points to the 
location of i*/

 The following statement gets the address of f 
and stores it as the value of the pointer
variable pf.
– pf = &f;  /* pf points to the 
location of f*/Mark De Vera
What operations can you
perform on pointers?
 Assign a value to a pointer variable

 Retrieve (read) the current value of a pointer
variable

 Dereference (a special read operation) a pointer
variable; this will be explained in more detail later

 Increment, decrement a pointer variable (pointer
arithmetic; will be discussed in detail later)
Mark De Vera
Assigning a value to a POINTER

There are basically three forms that you
will encounter, namely:

1. The pointer variable is assigned the
address of a variable, examples have
already been given above
pi = &i;
pf = &f;
Mark De Vera
Assigning a value to a POINTER

2. The value of pointer variable may also
be assigned to a pointer of the same
data type.

Note that this kind of assignment statement
retrieves the current value of the pointer variable at
the left hand side of the assignment operator.
For example:
ptemp = pi;
Mark De Vera
Valid or Invalid?

pf = pi;

invalid
because pf and pi do not have the same data type

Mark De Vera
Assigning a value to a POINTER

3. A pointer variable may be assigned a
value of NULL; it is a special value that
means that the pointer is not pointing to
any address.
Example:
pi = NULL;
ptemp = NULL;
pf = NULL;
Mark De Vera
Valid or Invalid?
ptemp = NULL;
pf = ptemp;

second assignment is invalid
even if ptemp has a value of NULL

 /*trying to set pf to NULL also;*/
/* invalid since pf and ptemp do 
not have the same data type*/
Mark De Vera
Dereference a pointer variable
Use the ‘dereference’ operator which is
denoted by the asterisk (*) character.

The dereferencing operation yields the value
of the memory where the pointer variable
points to.

This is what we mean by indirect memory
access.
Mark De Vera
Example
i = *pi + 5;
printf(“i= %d, *pi = %d\n”, i, 
*pi);

Key Points!
- pi is of type int * , i.e., integer pointer
­ *pi is of type int, thus, any operation that can be
performed on an integer variable can be performed
on *pi Mark De Vera
Example A – use of & and *
void main(void) /*sample use of the address­
{ of operator*/
char ch; pch = &ch;
int i; pi = &i;
float f; pf = &f;
double d; pd = &d;
char *pch; /*sample use of the 
int *pi; dereference operator*/
float *pf; printf(“ch = %d\n”, 
double *pd; *pch);
ch = ‘A’; printf(“i = %d\n”, 
i = 10; *pi);
f = 3.1416; printf(“f = %f\n”, 
d = 105.1; *pf); Mark De Vera
printf(“d = %lf\n”, 
Key Points!
- in the example above, the order of declaration
of variables is actually immaterial
- pointers may be set even before initializing
non-pointer variables
- make sure that the memory dereferenced
with the pointer contains a valid value,
otherwise if it is not initialized properly, the
data will be garbage resulting into a logical
error
Mark De Vera
Example B
The following shows that a value can be
accessed indirectly using several pointers to
the same memory location.
void main(void)
{ printf(“i = %d\n”, i);
int i, j; /*access the same value indirectly
int *p1, *p2, *p3;    pointers p1, p2 and p3*/
p1 = &i; printf(“*p1 = %d\n”, *p1);
p2 = p1; printf(“*p2 = %d\n”, *p2);
p3 = p1;  printf(“*p3 = %d\n”, *p3);
}
/*p1, p2, p3 all points to i*/
*p1 = 10; 
/* note that i will be also be 10
Mark De Vera
 access the value 10 directly via i*/
Example C - Can you find the
errors?
void main(void)
{
int i;
int *p1;
printf(“p1 = %u\n”, p1);  // 
ERROR: p1 not initialized

printf(“*p1 = %d\n”, *p1);  // ERROR: no 
real memory block

p1 = i;  // ERROR: p1 is pointer, i 
is integer

p1 = 100;   // ERROR: not 
really a memory address

p1 = &i;
printf(“*p1 = %d\n”, *p1);  // ERROR: i not 
initialized Mark De Vera

}
Hands-on Ex 1
Create a FUNCTION that will SWAP
values of x and y

Ex:
Initial Value After Swap
x=5 x=10
y=10 y=5
Mark De Vera
Key
#include <stdio.h>
/* swap the contents of memory pointed to by px and py*/
void swap (int *px, int *py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
void main(void)
{
int x, y;
x = 5;
y = 10;
Swap(&x, &y); /*pass the addresses of x and y as parameters*/
printf(“x = %d, y = %d\n”, x, y);
}
Mark De Vera
Key Points!
- the address of the variable should be passed
as parameter to change the contents of the
variable outside the block where it was
defined (and this is the only way!)

- now, do you understand why scanf() 
requires an ampersand before the variable
name, for example, scanf(“%d”, &n)?

Mark De Vera
relationship between
pointers and arrays
 Pointers and arrays are tightly related in
the C programming language. Array
elements can be accessed using
pointers.

Example:
int a[5];
int *pa;
Mark De Vera
relationship between
pointers and arrays
 Assume that the array a[] has been
initialized to some value. We can set pa 
to point to the first element of the array
by

pa = &a[0];

Mark De Vera
Thereafter, the pointer to
a[1] is pa + 1
a[2] is pa + 2
a[3] is pa + 3

In general, if pa is a pointer to an element of
an array, then pa + i is the pointer to the
memory which is i elements after pa and
pa–i points to the memory which is i 
elements before pa.
Mark De Vera
Elements are accessed by
dereferencing of the form
*pa

*(pa + i) 
(parentheses are used since * has higher priority than +)

*(pa – i) 
(parentheses are used since * has higher priority than –)

Mark De Vera
Example

The following example shows how to
access the elements of an array
indirectly by assigning the memory
location of each element to a pointer
inside a for-loop

Mark De Vera
void main(void)
{
     int a[5];
     int *pa;
     int i;
      /* initialize the array*/
     for (i = 0; i < 5; i++)
          a[i] = 5 – i;
     /* print the contents of the array*/
     for (i = 0; i < 5; i++)
    {
          pa = &a[i];  /*get i’th element 
address*/
          printf(“a[%d] = %d\n”, i, 
*pa); Mark De Vera

     }
Example 2
The following codes accomplishes the same
task (Example 1), but take note of the
difference in the code.
/*INSERT OTHER CODES HERE*/
/*print the contents of the array*/
pa = &a[0];
for (i = 0; i < 5; i++)
{
printf(“a[%d] = %d\n”, i, *(pa + 
i)); Mark De Vera

}
Can you do this?

Using the above code… print the
contents of the array in reverse order

Mark De Vera
Answer
/* INSERT OTHER CODES HERE*/
/*print the contents of the 
array*/
pa = &a[4];
for (i = 0; i < 5; i++)
{
printf(“a[%d] = %d\n”, i, *(pa 
­ i)); Mark De Vera
Notes
 In
C programming language, the array’s
name is a synonym for the location of
the first element. Thus, the statement
pa = &a[0]
… can be rewritten as
pa = a

Mark De Vera
Notes
 In general, the following equivalence holds
&a[i] == a + i

Therefore, the reference to
a[i]
can be rewritten as
*(a + i)

Mark De Vera
Notes
 Infact, the C programming language
automatically converts the form

a[i] to *(a + i).

Mark De Vera
Example 3
The following is an alternative implementation
of how to print the contents of an array.

/* INSERT OTHER CODES HERE*/
/* print the contents of the 
array*/
for (i = 0; i < 5; i++)
{
printf(“a[%d] = %d\n”, i, *(a + 
i)); Mark De Vera

}
Pointer Arithmetic
A limited set of arithmetic operations,
specifically, addition and subtraction
can be performed on pointers (i.e.,
memory addresses). This is basically
what we refer to as pointer arithmetic.

Mark De Vera
Example 1 - Incrementing pointers
void main(void) printf(“a[0] = 
%d\n”, *pa);
{ pa++;
int a[5]; printf(“a[1] = 
int *pa; %d\n”, *pa);
int i; pa++;
printf(“a[2] = 
/*initialize 
%d\n”, *pa);
the array*/
pa++;
for (i = 0; i  printf(“a[3] = 
< 5; i++) %d\n”, *pa);
a[i] = 5 – i; pa++;
pa = &a[0]; printf(“a[4] = 
Mark De Vera
void main(void)
{
int a[5];
Example 2 int *pa;
int i;
/*initialize the array*/
 Notethat the for (i = 0; i < 5; 
i++)
increment is a[i] = 5 – i;
not necessarily pa = &a[0];
1, negative %d\n”, *pa);
printf(“*pa = 

increments are pa = pa + 3;
also being printf(“*pa = 
%d\n”, *pa);
used. pa = pa ­ 2;
printf(“*pa = 
%d\n”, *pa);
Mark De Vera
pa­­;
printf(“*pa = 
Example 3
Alternative method of accessing contents of
array

/*INSERT OTHER CODES HERE*/
/*print the contents of the array*/
pa = &(a[0]);
for (i = 0; i < 5; i++)
{
printf(“a[%d] = %d\n”, i, *pa);
pa++; Mark De Vera

}
Exercise No. 3
 Assume that A is an array of 20 float data
type values. Assume also that pf is a float
pointer. Write a program that will:
– (1) initialize the array,
– (2) set the pointer pf such that it points to the
first element of the array and
– (3) print all the elements of the array from the
first down to the last by performing pointer
arithmetic and dereferencing on pf.
Mark De Vera
Memory Allocation
Memory allocation is an operation
wherein a specified amount of memory
space is reserved for storage of data.

Mark De Vera
Types of Memory Allocation
 Static
memory allocation
 Dynamic memory allocation

Mark De Vera
Static Memory Allocation
 memory space is allocated by the
system automatically.
 Memory will be reserved for use of a
variable throughout its lifetime
 This memory allocation scheme is
simple but not flexible enough for some
purposes

Mark De Vera
Static Memory Allocation
 Example: int a[10];
– This memory space will be reserved even if it is
not actually used by the user
– Waste of memory space
– On the other hand, it is possible that the user may
need more than ten memory spaces.
– In such a case, the only way to handle this is to
stop the program, change the array size in the
source code, compile and link the program again.

Mark De Vera
Dynamic Memory Allocation
 memory allocation is controlled by the user
(programmer)
 Memory can be requested and allocated
when needed, and relinquished when it is not
going to be used anymore by the program
 this scheme is very flexible and makes good
use of the memory resource
 it entails responsibility on the user
(programmer) to exercise care when writing
the source codes
Mark De Vera
Allocating memory statically

 The system automatically handles static
memory allocation.
 Memory is allocated and deallocated
automatically depending on the
variable’s scope.

Mark De Vera
Allocating memory dynamically
<pointer name> = malloc(<size of data type> * 
<count>)

- malloc is a pre-defined ANSI C function

Note that there are two possibly outcomes, namely:
(6) If there is an available memory, it will be allocated and the
pointer will then set to the address of the first byte.

(2) If memory is not enough, then the request for memory
cannot be satisfied. In such a case, the pointer will be set
to the value NULL.
Mark De Vera
De-allocating memory dynamically
 Memory which have been allocated
dynamically should be relinquished explicitly
by the programmer so that it can be used for
future memory requests.

 In C language, memory is de-allocated
(relinquished) by calling the ANSI function
free(). The syntax is:

free(<pointer name>)
Mark De Vera
Example 1
#include <stdio.h>
void main(void)
{
char *pch;
int *pi;
float *pf;
double *pd;

Mark De Vera
/*allocate memory dynamically*/
pch = (char 
*)malloc(sizeof(char));
pi = (int 
*)malloc(sizeof(int));
pf = (float 
*)malloc(sizeof(float));
pd = (double 
*)malloc(sizeof(double));
/*assign data to dynamically 
allocated memory*/
*pch = ‘A’;
*pi = 10;
*pf = 3.1416;
*pd = 88.3;
/*some other operations…*/
/*free memory*/ Mark De Vera
free (pch);
Example 2 - dynamic memory
allocation of multiple elements.
#include <stdio.h> // initialize the memory block
void main(void) for (i = 0; i < 5; i++)
{ *(pa + i) = 5 – i;
int *pa; // print the contents of memory block
for (i = 0; i < 5; i++)
int i;
{
pa = (int 
printf(“Element %d = %d\n”, i, *(pa +
*)malloc(sizeof(int) * 
5); }
free(pa);
if (pa == NULL)
}
{
print(“ERROR: no more 
memory.\n”);
exit(1);
} Mark De Vera
Example 3 – Alternative to Ex 2

/*initialize the memory block*/
for (i = 0; i < 5; i++)
pa[i] = 5 – i;
/*print the contents of memory 
block*/
for (i = 0; i < 5; i++)
{
printf(“Element %d = %d\n”, i, 
pa[i]); Mark De Vera

}
Key Points!
- the statement *(pa+i) is equivalent to
pa[i] and vice-versa
- Which form is better to use? The result
is the same, choose any form that is
best for you!

Mark De Vera
What are some of the things you should be
careful of when handling pointers?

Forgetting to properly initialize a pointer

Dereferencing a pointer which does not properly
point to a valid address

Not freeing the dynamically allocated memory

Mark De Vera
Quiz No 2
 Write a program that will dynamically
allocate contiguous memory for 10
floating point values.
 Check for the memory space, if the
memory is full the program should
display the message: “ERROR: Memory
Full” then exit.
 Floating values should come from the
user.
 Print the user’s inputs.
Mark De Vera