8.1. - Pointers
8.1. - Pointers
8.1. - Pointers
Unit 8 Pointers – I
Structure:
8.1 Introduction
Objectives
8.2 Basics of Pointers
8.3 Pointers and One-dimensional Arrays
Pointer Arithmetic
Pointer Subtraction and Comparison
Similarities between Pointers and One-dimensional Arrays
8.4 Summary
8.5 Terminal Questions
8.6 Answers to Self Assessment Questions
8.7 Answers to Terminal Questions
8.8 Exercises
8.1 Introduction
In the previous unit, you studied about the arrays and strings. You studied
how the arrays and strings are declared and manipulated in making C a
more easy and powerful programming language. In this unit, you will study
about pointer which is another useful topic that makes C a most powerful
programming language. You will study about the basics of pointer and
pointer arithmetic.
A pointer is a variable that points at, or refers to, another variable. That is, if
we have a pointer variable of type “pointer to int, “it might point to the int
variable i, or to any one of the locations of the int array a. Given a pointer
variable, we can ask questions like, “what’s the value of the variable that this
pointer points to?”.
Why would we want to have a variable that refers to another variable? Why
not just use that other variable directly? Pointers are used frequently in C,
as they have number of useful applications. For example, pointers can be
used to pass information back and forth between a function and its
reference point. In particular, pointers provide a way to return multiple data
items from a function via function arguments. Pointers also permit
references to other functions to be specified as arguments to a given
function. This has the effect of passing functions as arguments to the given
function.
Pointers are also closely associated with the arrays and therefore provide
an alternate way to access individual array elements. Pointers make the
program efficient when we use pointers for accessing the individual array
elements. In this unit, you will study about the basics of pointers and its
usage in one dimensional array.
Objectives:
After studying this unit, you should be able to:
implement pointers in your program
write a program related to arrays and using a pointer with it
solve and illustrate the use of pointer arithmetics in C
point out the similarities between pointers and one dimensional arrays
declaring, is not of type int, but rather of type pointer-to-int. (Another way of
looking at it is that *ip, which as we'll see is the value pointed to by ip, will be
an int.)
We may think of setting a pointer variable to point to another variable as a
two-step process: first we generate a pointer to that other variable, and then
we assign this new pointer to the pointer variable. We can say (but we have
to be careful when we're saying it) that a pointer variable has a value, and
that its value is “pointer to that other variable”. This will make more sense
when we see how to generate pointer values.
Pointers (that is, pointer values) are generated with the “address-of”
operator &, which we can also think of as the “pointer-to” operator. We
demonstrate this by declaring (and initializing) an int variable i, and then
setting ip to point to it:
int i = 5;
ip = &i;
The assignment expression ip = &i; contains both parts of the “two-step
process”: &i generates a pointer to i, and the assignment operator assigns
the new pointer to (that is, places it “in”) the variable ip. Now ip “points to” i,
which we can illustrate with this picture:
printf("%d\n", *ip);
which would print 5, since ip points to i, and i is (at the moment) 5.
(You may wonder how the asterisk * can be the pointer contents-of operator
when it is also the multiplication operator. There is no ambiguity here: it is
the multiplication operator when it sits between two variables, and it is the
contents-of operator when it sits in front of a single variable. The situation is
analogous to the minus sign: between two variables or expressions it's the
subtraction operator, but in front of a single operator or expression it's the
negation operator. Technical terms you may hear for these distinct roles are
unary and binary: a binary operator applies to two operands, usually on
either side of it, while a unary operator applies to a single operand.)
The contents-of operator * does not merely fetch values through pointers; it
can also set values through pointers. We can write something like
*ip = 7;
which means “set whatever ip points to 7.” Again, the * tells us to go to the
location pointed to by ip, but this time, the location isn't the one to fetch from
-- we're on the left-hand sign of an assignment operator, so *ip tells us the
location to store to. (The situation is no different from array subscripting
expressions such as a[3] which we've already seen appearing on both sides
of assignments.)
The result of the assignment *ip = 7 is that i's value is changed to 7, and the
picture changes to:
and write
ip = &j;
we've changed ip itself. The picture now looks like this:
This works for one pointer, because C essentially ignores whitespace. But if
you ever write
int* ip1, ip2; /* PROBABLY WRONG */
it will declare one pointer-to-int ip1 and one plain int ip2, which is probably
not what you meant.
What is all of this good for? If it was just for changing variables like i from
5 to 7, it would not be good for much. What it's good for, among other things,
is when for various reasons we don't know exactly which variable we want to
change.
Program 8.1: A simple program to illustrate the relationship between
two integer variables, their corresponding addresses and their
associated pointers.
#include<stdio.h>
main()
{
int x=5;
int y;
int *px; /* pointer to an integer */
int *py; /* pointer to an integer */
px=&x; /* assign address of x to px */
y=*px; /* assign value of x to y */
py=&y; /* assign address of y to py */
printf(“\nx=%d &x=%u px=%u *px=%d”, x, &x, px, *px);
printf(“\ny=%d &y=%u py=%u *py=%d”, y, &y, py, *py);
}
Execute this program and observe the result.
We'd use this ip just like the one in the previous section: *ip gives us what ip
points to, which in this case will be the value in a[3].
8.3.1 Pointer Arithmetic
Once we have a pointer pointing into an array, we can start doing pointer
arithmetic. Given that ip is a pointer to a[3], we can add 1 to ip:
ip + 1
What does it mean to add one to a pointer? In C, it gives a pointer to the cell
one farther on, which in this case is a[4]. To make this clear, let's assign this
new pointer to another pointer variable:
ip2 = ip + 1;
Now the picture looks like this:
If we now do
*ip2 = 4;
we've set a[4] to 4. But it's not necessary to assign a new pointer value to a
pointer variable in order to use it; we could also compute a new pointer
value and use it immediately:
*(ip + 1) = 5;
In this last example, we've changed a[4] again, setting it to 5. The
parentheses are needed because the unary “contents of'' operator * has
higher precedence (i.e., binds more tightly than) the addition operator. If we
wrote *ip + 1, without the parentheses, we'd be fetching the value pointed to
by ip, and adding 1 to that value. The expression *(ip + 1), on the other hand,
accesses the value one past the one pointed to by ip.
Given that we can add 1 to a pointer, it's not surprising that we can add and
subtract other numbers as well. If ip still points to a[3], then
*(ip + 3) = 7;
sets a[6] to 7, and
*(ip - 2) = 4;
sets a[1] to 4.
Up above, we added 1 to ip and assigned the new pointer to ip2, but there's
no reason we can't add one to a pointer, and change the same pointer:
ip = ip + 1;
Now ip points one past where it used to (to a[4], if we hadn't changed it in
the meantime). The shortcuts work for pointers, too: we could also
increment a pointer using
ip += 1;
or
ip++;
Of course, pointers are not limited to ints. It's quite common to use pointers
to other types, especially char.
When you're doing pointer arithmetic, you have to remember how big the
array the pointer points into is, so that you don't ever point outside it. If the
array a has 10 elements, you can't access a[50] or a[-1] or even a[10]
(remember, the valid subscripts for a 10-element array run from 0 to 9).
Similarly, if a has 10 elements and ip points to a[3], you can't compute or
and the answer is, yes. When you subtract two pointers, as long as they
point into the same array, the result is the number of elements separating
them. You can also ask (again, as long as they point into the same array)
whether one pointer is greater or less than another: one pointer is “greater
than” another if it points beyond where the other one points. You can also
compare pointers for equality and inequality: two pointers are equal if they
point to the same variable or to the same cell in an array, and are
(obviously) unequal if they don't. (When testing for equality or inequality, the
two pointers do not have to point into the same array.)
you can refer to *ip, *(ip+1), *(ip+2), etc., or to *(ip+i) where i is an int.
There are also differences, of course. You cannot assign two arrays; the
code
int a[10], b[10];
a = b; /* WRONG */
is illegal. As we've seen, though, you can assign two pointer variables:
int *ip1, *ip2;
ip1 = &a[0];
ip2 = ip1;
Pointer assignment is straightforward; the pointer on the left is simply made
to point wherever the pointer on the right does. We haven't copied the data
pointed to (there's still just one copy, in the same place); we've just made
two pointers point to that one place.
The similarities between arrays and pointers end up being quite useful, and
in fact C builds on the similarities, leading to what is called “the equivalence
of arrays and pointers in C.'' When we speak of this “equivalence'' we do not
mean that arrays and pointers are the same thing (they are in fact quite
different), but rather that they can be used in related ways, and that certain
operations may be used between them.
The first such operation is that it is possible to (apparently) assign an array
to a pointer:
int a[10];
int *ip;
ip = a;
What can this mean? In that last assignment ip = a, C defines the result of
this assignment to be that ip receives a pointer to the first element of a. In
other words, it is as if you had written
ip = &a[0];
The second facet of the equivalence is that you can use the “array
subscripting'' notation [i] on pointers, too. If you write ip[3]
it is just as if you had written
*(ip + 3)
8.4 Summary
A pointer is a variable that points at, or refers to, another variable. The
general format of a simple pointer declaration is: datatype *variablename.
We discover the value pointed to by a pointer using the “contents-of”
operator, *. Pointers are very useful when you want to refer to some other
variable by pointing at it. Pointers not only point to single variables but can
also point at the cells of an array. Pointers are also closely associated with
the arrays and therefore provide an alternate way to access individual array
elements. Once we have a pointer pointing into an array, we can do some
pointer arithmetic-add a constant to a variable or subtract a constant from a
pointer, or you can subtract two pointers. There are similarities between
pointers and one dimension arrays in some aspects although they are
entirely different concepts and there are differences also in other aspects.
8.8 Exercise
1. Write a program that uses the pointer arithmetic.
2. Write a program that can accept any 5 data and sort it in ascending
order using pointers.
3. With the help of pointers, write a program that uses functions to swap
the data.
4. What are the various operators that are used when implementing a
pointer in a program? Explain with an example.