Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 18

POINTERS

INTRODUCTION:
Computers use their memory for storing the instructions of a
program, as well as the values of the variables that are associated with it.
The computer’s memory is a sequential collection of ‘Storage Cells’. Each cell,
commonly known as a byte, has a number called address associated with it.
Whenever we declare a variable, the system allocates, somewhere in
the memory, an appropriate location to hold the value of the variable. Since,
every byte has a unique address, this location will have its own address.
Consider the following statement:
int var=10;
This statement instructs the system to find a location for the integer
variable ‘var’ and puts the value 10 in that location. Let us assume that the
system has chosen the address the location 2000 for ‘var.
var
10
2000
During execution of the program, the system always associates the
quantity with the address 2000(this is similar to having house no as well as
the house name). We may have access the value 10 by using either the name
‘var’ or the address 2000. Since memory addresses are simply numbers, they
can be assigned to some variables which can be stored in memory, like any
other variable. Such variables that hold memory addresses are called
pointers.
Def: Pointer is variable that contains an address which is a location of
another variable in memory.

ptr var
2000 10
3000 2000
Since a pointer is a variable, its value is also stored in the memory in
another location. Suppose, we assign the address of var to a variable ptr.
The link between the variable ptr and var visualized as shown in fig.
Since the value of the variable ptr is the address of the variable var,
we may access the value of var by using the value of ptr and therefore, we

1
say that the variable ptr points to the variable var. Thus ptr gets name
‘pointer’.
POINTER VARIABLE DECLARATION AND INITIALIZATION:
The actual location of a variable in the memory is system dependent.
To know the address of the variable C provides a operator called ampersand
(&). This operator returns the address of the variable.
To print the address of the variable we have to use %u or %x.
Since the memory address are unsigned integers. If we used %u it prints
positive integer and if we use %x it prints the address in hexadecimal
format.
ch i a
A
10 38.73
65525 fff2 ffee

#include<stdio.h>
#include<conio.h>
void main()
{
char ch='A'; Output:65525
int i=10; fff2
float m=38.73; ffee
clrscr();
printf("%c is stored at addr %u\n",ch,&ch);
printf("%d is stored at addr %x\n",i,&i);
printf("%f is stored at addr %x\n",m,&m);
getch();
}

POINTER DECLARATION:
In C, every variable must be declared for its type. Since pointer
variables contains addresses that belong to a separate data type, they must
be declared as pointers before we use them. The general format of format
declaration is
datatype *pt_name;
This tells the compiler three things about the variable pt_name
1. The asterisk(*) tells that the variable pt_name is a pointer variable.
2. pt_name needs a memory location.

2
3. pt_name points to variable of type datatype.

Example: int *ptr;

This declaration tells that the variable points to an integer datatype.


INITIALIZING POINTERS:
Once a pointer variable has been declared, it can be made to point a
variable using an assignment statement such as
int i=10,*ptr;
ptr=&i; or int *ptr=&i;
which causes ptr to point to i. That is, p now contains the address of i.
Note: A pointer declared of one datatype cannot point to
variable of another datatype.
We must ensure that the pointer variables always pointing to the
corresponding type of data. For example
float a,b;
int x,*p;
p=&a; (Error because we are assigning int pointer to float var)
p=&x;
will result in erroneous output because we are trying to assign the address
of a float variable to an integer pointer. When we declare a pointer to int
type, the system assumes that any address that this pointer will hold will
point to an integer variable.
ACCESSING A VARIABLE THROUGH ITS POINTER:
Once a pointer has been assigned the address of a variable, we can
access the value of the variable using this pointer . This is done by using
another unary operator *(asterisk), known as the indirection operator.

1. int x,*ptr,y;
2. x=10;
3. ptr=&x;
4. y=*ptr;
5. *ptr=25;

4106 4104 4102

Ptr x y

3
Ptr x y

10

4104 10

4104 10 10

4104 25 10

The first line declares x, y and a pointer varaiable ptr to an integer


datatype. The second line assigns the value 10 to x and the third line assigns
the address of x to the pointer variable ptr. The fourth line contains
indirection operator *. When the operator * is placed before a pointer
variable in an expression(on the right side of equal sign), the pointer returns
the value of the variable of which the pointer points. It indicates ‘value at
address’. In this case *ptr returns (10) the value of the variable x to y,
because ptr points to variable x.
The last line indicates that the value 25 is stored at the memory location
where the ptr pointer is pointing i.e at x because the ptr pointer is pointing
to x.
Example:
#include<stdio.h>
#include<conio.h>
void main()
{
int x=10,y;
int *ptr;
clrscr();
ptr=&x;
y=*ptr;
printf("The value in the pointer variable %u\n",ptr);
printf("value at where the pointer is pointing %d\n",*ptr);
printf("The value assigned to y is %d\n",y);
getch();
}

4
The output of the program is:
The value in the pointer variable 65532
value at where the pointer is pointing 10
The value assigned to y is 10

Example 2: #include<stdio.h>
#include<conio.h>
void main()
{
int x=10,y;
int *ptr1,*ptr2;
clrscr();
ptr1=&x;
ptr2=&y;
*ptr2=*ptr1;/*Assigning value at ptr1 to point ptr2 points*/
printf("The value at ptr2 points (i.e y value) %d",*ptr2);
getch();
}

The output of the program is:


The value at ptr2 points (i.e y value) is 10.

Example: #include<stdio.h>
#include<conio.h>
void main()
{
int a,b,c,d;
int *ptr1,*ptr2,*ptr3,*ptr4;
clrscr();
ptr1=&a;
ptr2=&b;
ptr3=&c;
ptr4=&d;
*ptr1=5;
*ptr2=*ptr1+5;
*ptr3=*ptr2**ptr1;
*ptr4=*ptr3/ *ptr2; (Give space btwn / and *)

5
printf("The values of a,b,c,d are %d %d %d %d",a,b,c,d);
getch();
}
OUTPUT: The values of a,b,c,d are 5 10 50 5

CALLING FUNCTIONS BY REFERENCE


There are two ways to pass arguments to a function –
1) Call by Value
2) Call by Reference
Call by Value: refers to sending value of arguments onto the function. In
this method, the value of actual arguments is copied onto the corresponding
formal arguments whenever a function is called. The various operations
performed on their(formal arguments) values of the function has no effect
on the value of actual arguments in the main function. The following example
clearly illustrates the call by value method.
a b a b
10 20 10 20

10 20 20 10
x y x y
Before Swapping After Swapping

#include<stdio.h>
#include<conio.h>
void swap(int,int);
void main()
{
int a=10,b=20;
clrscr();
printf("value of a before function call= %d\n",a);
printf("value of b before function call= %d\n",b);
swap(a,b); /*a&b are actual arguments*/
printf("value of a after function call= %d\n",a);
printf("value of b after function call= %d\n",b);
getch();
}
void swap(int x,int y)/*x & y are formal arguments*/

6
{
int temp;
temp=x;
x=y;
y=temp;
printf("value of a in the function = %d\n",x);
printf("value of b in the function = %d\n",y);
}

The output of the above program is:


value of a before function call= 10
value of b before function call= 20
value of a in the function = 20
value of b in the function = 10
value of a after function call= 10
value of b after function call= 20

Call by Reference is a method , in contrast to call by value method, the


operations performed on the formal arguments directly effects the value of
actual arguments . This is because the formal arguments contains the
address of actual arguments, so any changes on that address effect the
values. The following program illustrates the call by reference method.

a(or)*x b(or)*y a b
10 20 20 10

4024 4026 4024 4026


x y x y
Before Swapping After Swapping

#include<stdio.h>
#include<conio.h>
void swap(int *,int *);
void main()
{
int a=10,b=20;
clrscr();

7
printf("value of a before function call= %d\n",a);
printf("value of b before function call= %d\n",b);
swap(&a,&b); /*passing addresses of variables*/
printf("value of a after function call= %d\n",a);
printf("value of b after function call= %d\n",b);
getch();
}
void swap(int *x,int *y)
{
int temp;
temp=*x;
*x=*y;
*y=temp;
printf("value of a in the function = %d\n",*x);
printf("value of b in the function = %d\n",*y);
}

The output of the above program is:


value of a before function call= 10
value of b before function call= 20
value of a in the function = 20
value of b in the function = 10
value of a after function call= 20
value of b after function call= 10

POINTER EXPRESSIONS AND POINTER ARTHMETIC


Pointers are valid operands in arithmetic expressions, assignment
expressions, and comparision expressions.
A limited set of arithmetic operations may be performed on pointers.
A pointer may be incremented(++) or decremented(--), an interger may be
added to a pointer(+ or +=), an integer may be subtracted from a pointer –or-
=) or one pointer may be subtracted from another.
Pointers are used with unary operators such as
incrementation ++
decrementation --
Pointers are variables which mainly store the address, they are not
integers or definite value of a particular data type. Therefore the increase
or decrease in pointer variable refers to the increment and decrement of

8
address not of data. For example, in case of integer type of pointer variable,
if the pointer variable is incremented then, the address of pointer will be
incremented by two address spaces. This is because one integer valued takes
two bytes to store therefore the increment in address will be of two
positions. This implies that the increment or decrement in pointer variable
depends on the type of pointer declared. The program given below will clear
this point.
Example: To display the address of pointer before and after incrementing.
#include<stdio.h>
#include<conio.h>
void main()
{
int a=10,*ptr;
clrscr();
ptr=&a;
printf("Addr of pointer(ptr) before increment:%u\n",ptr);
ptr++;
printf("Addr of pointer(ptr) after increment:%u\n",ptr);
getch();
}
OUTPUT: Addr of pointer(ptr) before increment:65522
Addr of pointer(ptr) after increment: 65524
The above program’s output shows that the ptr of integer type
contains address of int a. therefore the initial address of the pointer will be
same as of integer a i.e 65522. After the incrementation operation, the
address of pointer increases by two positions i.e 65524. This is because
the pointer taken is of integer type and one integer takes two bytes to
store.
Similarly, the position/ address of pointer decreases when a
decrementation operation is performed on it. The program given below show
s the decrement of pointer variable.

Example: To display the address of a pointer variable before and after


decrementing.
#include<stdio.h>
#include<conio.h>
void main()
{

9
int a=10,*ptr;
clrscr();
ptr=&a;
printf(“The addres of ptr before decrement:%u”,ptr);
ptr--;
printf(“The address of ptr after decrement:%u”,ptr);
getch();
}

OUTPUT: The address of ptr before decrementation: 65524


The address of ptr after decrementation : 65520
The above program’s output clearly shows that since pointer taken is
of float type therefore the decrementation operation on pointer leads to
decrease in four address spaces.
Pointers are also used with arithmetic operators for increment and
decrement of address spaces. The arithmetic operators used are + and –(not
* and /). The following program shows the arithmetic operators with
pointers to .
To demonstrate arithmetic operations on pointers
#include<stdio.h>
#include<conio.h>
void main()
{
int a=10,*ptr1,*ptr2,*ptr3;
clrscr();
ptr1=&a;
printf("Adress of pointer(ptr1) is %u\n",ptr1);
ptr2=ptr1+2;
printf("Address of pointer(ptr2) is %u\n",ptr2);
ptr3=ptr1-2;
printf("Address of pointer(ptr3) is %u\n",ptr3);
getch();
}
OUTPUT: Address of Pointer(ptr1) is 65524
Address of pointer(ptr2) is 65528
Address of pointer(ptr3) is 65520

10
In above program, pointers ptr1,ptr2 and ptr3 are of integer type.
Pointer ptr1 is assigned the address of integer a. Pointer ptr2 is assigned as
pointer ptr1 plus 2. This means that, since ptr1 is an integer variable, there
the addition of 2 to it leads to addition in address two times i.e by 4.
Similarly, pointer ptr3 is assigned as pointer ptr1 minus 2. This means
that ptr3 is equal to substraction of 2 from ptr1 which leads to decrease in
address two times i.e by 4 .
One pointer variable can be subtracted from another provided both
variables point to element of the same. The resulting value indicates the
number of bytes separating the corresponding array elements. This is
illustrated in the following program.
Example: #include<stdio.h>
#include<conio.h>
void main()
{
int a[]={10,20,30,45,67,56,74,90};
int *i,*j;
clrscr();
i=&a[1]; Output: 4 36
j=&a[5];
printf("\t%d\t%d",j-i,*j-*i);
getch();
}
1000 1002 1004 1006 1008 1010 1012 1014
10 20 30 45 67 56 74 90

1002 1010
i j
Here i and j have been declared as integer pointers holding addresses
of first and fifth element of the array respectively.
Suppose the array begins at location 1000, then the elements a[1] and
a[5] would be present at location 1002 and 1010 respectively since each
integer in the array occupies two bytes in memory. The expression j-i would
print a value 4 not 8. This is because j and I are pointing to locations which
are 4 integers apart. What would be the result of the expression *j-*i? 36,

11
since *i and *j return the values present at addresses contained in the
pointers i and j i.e 20 and 56. Therefore, *j-*I results 36.

Do not attempt the following operations on pointers, they would never work.
1) Addition of two pointers (i.e ptr1+ptr2)
2) Multiplication of a pointer with a constant ( i.e ptr*3) and
multiplication of pointer with a pointer (i.e ptr1*ptr2).
3) Division of a pointer with a constat(i.e ptr/4) and division of pointer
by a pointer(i.eptr1/ptr2).

POINTER COMPARISION
Pointer variables can be compared provided both variables point to
objects of the same data type. Such comparisons can be useful when both
pointer variables point to elements of the same array. The comparison can
test for either equality or inequality. Moreover a pointer variable can be
compared with zero(usually expressed as NULL). The following program
illustrates how the comparison is carried out.

Example: #include<stdio.h>
#include<conio.h>
void main()
{
int arr[]={10,20,36,72,12,38};
int *p,*q;
clrscr();
p=&arr[4];
q=&arr[4];
if(p==q)
printf("The two pointers point to the same location");
else
printf("The two pointers do not point to same location");
getch();
}
OUTPUT: The two pointers point to the same location.

12
THE RELATIONSHIP BETWEEN POINTERS AND ARRAYS
When an array is declared, the compiler allocates a base address and
sufficient amount of storage to contain all elements of the array in
contiguous memory locations. The base address is the location of the first
element(index 0) of the array. The compiler also defines the array name as a
constant pointer to the first element. Suppose we declare an array x as
follows:
int x[5]={1,2,3,4,5};
Suppose the base address of x is 1000 and assuming that each integer
requires two bytes, the five elements stored as follows:
x[0] x[1] x[2] x[3] x[4]
1 2 3 4 5
1000 1002 1004 1006 1008
Base address
The name x is defined as a constant pointer pointing to the first
element, x[0] and therefore the value of x is 1000, the location where x[0]
is stored. That is,
X=&x[0]=1000
If we declare ptr as an integer pointer, then we can make the pointer
ptr to point to the array x by the following assignment
int *ptr; or int *ptr;
Ptr=x; ptr=&x[0];

ptr x[0] x[1] x[2] x[3] x[4]


1000 1 2 3 4 5
2000 1000 1002 1004 1006 1008

Now the pointer ptr is pointing to starting address of the array. The
pointer expression to represent the address of a[3](i.e &a[3]) is
Ptr+3
and the pointer expression to represent the value at a[3] is
*(ptr+3) ( Value at that address)
Here the parenthesis is necessary because the precedence of * is higher
than the precedence of +. With out parenthesis, the above expression would
add 3 to the value of the expression *ptr(i.e 3 is added to x[0] assumed ptr
is pointing to the beginning of the array).

13
Now, we can access every value of x using ptr++ to move from one
element to another. The relationship between ptr and x is shown below.

ptr = &x[0] = 1000 *ptr = x[0] = 1


ptr+1 = &x[1] = 1002 *(ptr+1) = x[1] = 2
ptr+2 = &x[2] = 1004 *(ptr+2) = x[2] = 3
ptr+3 = &x[3] = 1006 *(ptr+3) = x[3] = 4
ptr+4 = &x[4] = 1008 *(ptr+4) =x[4] = 5

The array name itself can be treated as pointer and used in pointer
arithmetic. For example, the expression
*(x+3)
also refers to the array element x[3]. In general, all subscripted array
expressions can be written with a pointer and offset. In this case,
poiter/offset notation was used with the name of the array as a pointer.
Note that the preceding statement does not modify the array name in any
way: x still points to the first element in the array.
Pointers can be subscripted exactly as arrays can. For example, the
expression
ptr[3]
refers to the array element x[3].
An array name is essentially a constant pointer; it always point to the
beginning of the array. Thus, the expression
x+=3
is invalid because it attempts to modify the value of the array name with
pointer arhtematic.
Example: #include<stdio.h>
#include<conio.h>
void main()
{
int x[]={10,20,30,40},*ptr,i;
ptr=x;/* set ptr to point to array x*/
clrscsr();
printf(" The array x printed with\n\n");
printf("\n\nArray subscript notation\n");
for(i=0;i<4;i++)
printf("x[%d] = %d\n",i,x[i]);

14
printf("\n\npointer/ offset notation where\n");
printf("the pointer is the array name\n");
for(i=0;i<4;i++)
printf("*(x+%d) = %d\n",i,*(x+i));
printf("\n\npointer subscript notation\n");
for(i=0;i<4;i++)
printf("ptr[%d] = %d\n",i,ptr[i]);
printf("\n\npointer/offset notation\n");
for(i=0;i<4;i++)
printf("*(ptr+%d) = %d\n",i,*(ptr+i));
getch();
}
OUTPUT: The array x printed with
Array subscript notation pointer/offset notation where
x[0]=10 the pointer is the array name
x[1]=20 *(x+0)=10
x[2]=30 *(x+1)=20
x[3]=40 *(x+2)=30
*(x+3)=40
Pointer subscript notation pointer/offset notation where
ptr[0]=10 *(ptr+0)=10
ptr[1]=20 *(ptr+1)=20
ptr[2]=30 *(ptr+2)=30
ptr[3]=40 *(ptr+3)=40

POINTERS AND STRINGS


Suppose we wish to store “Hyderabad”. We may store it in a
character array or we may ask the compiler to store it at some location in
memory and assigns the address of the string in a char pointer. This is
shown below
Char str1[ ]=”Hyderabad”;
Char *ptr= ”Hyderabad”;

Example: #include<stdio.h>
#include<conio.h>
void main()
{
char arr[10]="Hyderabad";

15
char *s="Hyderabad";
clrscr();
printf("%s\n",arr);
printf("%s",s);
getch();
}

a[0]………………………………………………..a[8] s 1000
H y d e r a b a d
1000 Hyderabad
d
Stored in array Pointer Some Mem loc
OUTPUT: Hyderabad
Hyderabad
Here, though the declarations of arr and s are different the output
of both the printf() is same. What exactly is the difference in the
declarations?. In the first declaration “Hyderabad” gets stored in array arr[
], whereas in the second “Hyderabad” gets stored at some place in memory
and the base address of it is stored in s. In other words s points to the
zeroth character in the string.
On mentioning the name of the array arr we get its base address.
Hence the following printf() would print the base address of arr and the
address stored in s.
printf(“%d %d”,arr,s);
In that sence arr acts as a pointer to a char. But the similarity between arr
and s ends there. The following program outlines this difference.
void main()
{
char str[ ],arr[10]="Hyderabad";
char *s="Hyderabad",*p;
s++;
arr++; /*Error because we are changing base address*/
str=arr;/*Error because we cannot assign*/
p=s;/* This statement works*/
printf("%s\n",arr);
}

Here s++ increments s such that it starts pointing to ‘y’ of


“Hyderabad” and hence printf() would output “yderabad”. As against this
arr++ would give an error message. This is because all that is known to the C

16
compiler about an array is its base address, and if we do arr++ we are
attempting to change this base address. This the C compiler would never
allow.
The other difference is we cannot assign a string to another, whereas,
we can assign a char pointer to another char pointer.

Another difference between arrays and pointers is the way the sizeof
operator treats them.
printf(“%d %d”,sizeof(s),sizeof(arr));
In this statement the first expression would print 2 since size of any
Pointer is 2 bytes. However, the second expression would print 10 because
the array contains 10 characters including ‘0’ .

ARRAY OF POINTERS
The way there can be an array of ints or an array of floats, similarly
there can be an array of pointers. Since a pointer variable always contains an
address, an array of pointers would be nothing but a collection of addresses.
The addresses present in the array of pointers can be addresses of isolated
variables or addresses of array elements or any other addresses.

The general format of declaring array of pointers is as follows


datatype *arr_name[sz];
Example: int *arr[5];
This indicates arr is the array which consists of pointers point to
integer data type.

Example: #include<stdio.h>
#include<conio.h>
void main()
{
int *arr[4];
int a=31,b=5,c=19,d=71,i;
clrscr();
arr[0]=&a;
arr[1]=&b;
arr[2]=&c;
arr[3]=&d;
for(i=0;i<4;i++)

17
printf("%d\t",*(arr[i]));
getch();
}
a b c d
31 5 19 71
4008 5116 6010 7118

4008 5116 6010 7118


arr[0] arr[1] arr[2] arr[3]
OUTPUT: 31 5 19 71
As u can observe, arr contains addresses of isolated int variables a,b,c
and d. The for loop in the program picks up the addresses present in arr and
prints the values present at these addresses.

Example:
#include<stdio.h>
#include<conio.h>
void main()
{
char *names[]={"abcd","pqrs","xyz","mnop"};
int i;
clrscr();
for(i=0;i<4;i++)
printf("%s\n",names[i]);
getch();
}
OUTPUT: abcd
pqrs
xyz
mnop

18

You might also like