Next: Examples of Pointers and Arrays Up:Main Previous: Pointers and Arrays
Pointers
We will continue our discussion on the pointers and how we
put this concept to use.
We have already seen
the representation of pointers in
a program, i.e. how do we declare pointers and how to get the address to which
it is pointing to. For example to declare a pointer "num" of the
type "integer" we used "int *num;". we
also saw that, to assign or to point this pointer to another integer variable "n" we will use the statement "num=&n;" .
Here we created a
pointer called num and then directed
this num to the address of the number
n.Thats what the use of "&" operator is . It returns the address of the
argument "n" and then assigns that to "num ".
Now we will see the use of
* operator. We are going to assign the value stored in the address, to
which "num" is pointing , to another variable "m" . The
way that is done is through the staement, "m=* num;" . Here * returns
the data to which "num " is pointing
to.
Remember that "*" and "&" are two operators that is
closely associated with a pointer.Then we come to arrays. The syntax to declare an integer array "m" of
four elements is int x[4]; The type here is integer and
array dimension is 4 . Now
elements of the array would be x[0],x[1],x[2] and
x[3]. Another important thing to
note is that we use square brackets instead of
() brackets to mark the elements of the
array. This is because we use () to represent functions.
Now we will see how one can use arrays and pointers
interchangeably. Let us look at the
following code.
int *num;
int x[4];
num=x;
Here we have an integer pointer declared num, which is of type int
and an integer array x . By saying num=x we are
point num to the base address of the array
x. i.e to the base element of x.
If we now write num++ it will point to the next element of the array x i.e. x[1].
There are two important things to take note of. We can point num to the " ith"element of the array by stating num=x[i]; .
num++; will then point to the "(i+1)th " element. The second point is that num++; can be
used recursively to point to the successive elements of the array. i.e.,
num=x;
for(i=0;i<=3;i++)
{num++;}
will make num point
to all the elements of the array successively and we can get the value stored
in the array elements by using "*num". However
if we look at the address of "num" it will
always be the base address of "x".
Printing the address of array
elements using pointers:
Pointers can be
used to get the address of each element of the array. Let is say we declare an array x in the following manner;
int x[ ]={10,20,30,40,50};
As you may have noticed this
way of declaring array is different from that we used earlier. Here, while
declaring the array, we have also assigned values to the elements.
So here "x" is an array and
we have given 10,20,30,40,50 as the elements of the array.
That is x[0]=10,x[1]=20,x[2]=30,x[3]=40
and x[4]=50.
We will now define another integer pointer " j " using the statement int *j; and
assign j=x; this statement basically mean "j" would point to the base address of an array "x".
Now we can read as the address of num[0] from j[0] and the
address of num[1] from j[1] etc.. We see this in the program given below .
(pointer-4.c)
#include<math.h>
#include<stdio.h>
main()
{
int x[ ]={10,20,30,40,50};
int i,*j;
j=x;
for(i=0;i<=4;i++)
{
printf("%u %u %d %d
\n",&j,&j[i],*j,x[i]);
j++;
}
}
This program implements the idea we just discussed to print out the
addresses of the array elements. It also points out many features
of pointers. Let us look at it in a
little more detail.
After the usual include statements the main program has the array declaration we
just discussed. Then we declare an integer i
and integer pointer j. Then the assignment j=x, which make j
point to the base address of the array x. Then we
get into the loop which execute the printf statement five times by incrementing "i" one
at a time. Each time it goes through the loop the pointer "j" is incremented by
one.
The printf statement prints out the addresses of "j" and "j[i]". As we
had discussed earlier the operator "&" will return the address of the variable or array following it. We are also
printing out the value stored in the address to which "j" is pointing and the value of the array element "x[i]".
This will demonstrate
the difference between the addresses of "j" and "j[i]. What we want to see here is that while the address given by "&j" remains the same the value given by "*j" changes, indicating that each time we increment "j" it is pointing to the next element of
array "x". but the operator "&" acting on "j" always return its base address. So to get the address of the array elements we
should use "&j[i]".
Note that we use % u as the format to
print out the addresses and %d to print
the value of an integer.
If we now compile and run the program using the commands,
gcc pointer-4.c
./a.out
the following lines will be printed on the screen;
4277678728 4277678736 10 10
4277678728 4277678744
20 20
4277678728 4277678752
30 30
4277678728 4277678760
40 40
4277678728 4277678768 50 50
As we expected the
first column is always printing the base
address of j, even though we are incrementing "j" by "j++". But "&j[i]", in the second column, is printing different numbers i.e it is giving us the address of the different
elements in array "x". So j[i] is pointing to the different elements of the array. The third column is "*j" and the fourth is "x[i]". You
can see that there are the same. That is what we expect to find.
To summarize what we
have seen here is that there are two ways to get the elements of an
array. One can point an integer pointer to the array, then increment that integer pointer and pick up the values using the "*" operator.
Or one could use array elements
straightaway. If you want to get the address of the array elements there is only one way of doing that. We the integer pointer is "j", printing &j we will not get the address of each elements. You could
get only the base address while "&j[i]" will give us the addresses of each
elements.
Pointer to Pointers:
We can
make a pointer to point to another
pointer i.e pointer to pointers. It
is useful when we want to read a character array and also a two dimensional
array as we will see later.
Let us look at a sample code.
char **marker;
char
course[0]="numerical",course[1]="methods";
marker=&course[0]; \* pointer
to course[0] which points to "numerical" */
marker++; \* points to course[1] which points to "m" in "methods" */
(*marker)++ \* will then point to "e" */
Here "marker" is a pointer
to a pointer, we use " ** marker " to declare this. In the sample code given above we also have character
array "course" . The first element of this character array is "course
[0]" which is storing the string "numerical" and the second element of the array is "course[1]" which is storing "methods".
In the third line of the sample code we point "marker" to "course[0]" . If we now increment "marker", by
using "marker++", it will point to "course[1]".
Question:How do one read out each of the characters in a string ?
Here is a program that does it.
(pointer-5.c)
#include<math.h>
#include<stdio.h>
main()
{
int i;
char **marker,*course[2];
course[0]="numerical";
course[1]="methods";
marker=&course[0];
for(i=0;i<=8;i++)
{
printf("%u %u %c
\n",&marker[i],&course[i],*(*marker));
(*marker)++ ;
}
}
This is the way we can do it. We have (*marker)++ which will move the pointer through "numerical", since "marker" is set to "course[0]".
The bracket is very important here. Instead if we use "marker++" the
pointer will shift to the next element of the array "course".
We have used "%c" to print
each characters of the string to which (*marker)
is pointing.
The printf statement also
prints out the address to which marker is pointing and also the address of the
array "course". You can compare these
addresses.
Here is the out put
of the program.
4277434920 4277434920 n
4277434924 4277434924
u
4277434928 4277434928
m
4277434932 4277434932
e
4277434936 4277434936
r
4277434940 4277434940
i
4277434944 4277434944
c
4277434948 4277434948
a
4277434952 4277434952 l
What happens if you change the increment of the pointer to "course++" ?
Passing variables to functions:
A good programmer does most of the calculations in sub
functions. When the "main" function (or other sub functions ) invoke a
particular sub function it may want to pass and receive some variables. In this
section we will look at how this is carried out.
We have seen the use of a function earlier but haven't
looked at how variables are passed.
(see below for general rules on calling a function). So
now we will see how arrays and variables are passed
from one function to another.
In this context the most important thing to remember is the following. In C all variables are passed by value
except arrays which are passed by reference. What do one means by "by value" and by "reference" ?
There are two things a function can do, when you pass variable
to it. The function can make a copy of
the variable and work with that copy or it can directly work on the variable.
In a C program the former method is adopted when we pass only the value of that
variable to the function. That is the
function gets a copy of the variable, stores it in a different location in the
memory, and it works with that copy. So
if you make a change in that variable value inside that function it doesnt
change the variable in the master function.
This is what we refer to as pass by value.
As opposed to this, in
pass by reference , we pass the address of the memory location where the
variable is stored. And now in the function if you change the value stored in
that location it will of course change it in the main program too. So the main
difference is that if you pass by ref it will not make a copy but if you pass by variable it will make a copy.
Passing an array to a function:
We do something quite different when we pass the content
of an array from one function to another.
This is because, as we had discussed earlier, the array name is also the
pointer to the first element of the array. So when you are passing an array to
another function, using the array name, you are passing pointer to the first
element of the array, that is we are
passing by reference.
In this case any, the
function that received this array is directly working with it, not with a copy
of it. So any change that is made in the array by the subfunction will also
change the value of the array in the program
from which its passed.
Summary:
All functions have the following form
type function
name (arguments passed to the funtion)
variable
declaration of the arguments
{
local
variable declarations
statements
}
Argument passing:
Two ways of passing variables are
(1) call by value
Here the function work with a copy of the
variable
changes
made in the function will not effect its value in
the calling
function
(2) call by reference
Here
the address of the variable is passed to the function.
changes made in the function will change its value in the
calling function.
We then pass all the three into a function "print". Thus
function receives "m" as "n", "num" as "b" and "j" as "l".