You are on page 1of 35

POINTERS

• A pointer is a derived data type.


• Pointers contain memory addresses as their values.
Pointers can be used to access and manipulate data
stored in the memory.
• 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. The addresses
are numbered consecutively starting from zero. The last
address depends on the memory size.
0
1
2 Memory Address
3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
65535

Memory cell
• Consider the declaration, int i =10;
• This declaration tells the compiler to
• reserve space in memory to hold integer value.
• associate the name i with this memory location.
• store the value 10 at this location.
i Location name

10 Value at location

65520 Location number

• Now we may have access to the value 10 either by using


the name i or the address 65520.
• Since memory addresses are simply numbers, they can
be assigned to some variables. Such variables that hold
memory addresses are called pointer variables.
• Pointers are based on three underlying concepts.
• Pointer constants
• Pointer values
• Pointer variables
• Memory addresses are referred to as pointer constants.
These cannot be changed and used to store data values.
• We cannot save the value of a memory address directly.
We can only obtain the value using the address of (&)
operator. The value thus obtained is the pointer value.
• Pointer value can be stored into another variable. The
variable that contains a pointer value is called a pointer
variable.
• A pointer variable is a variable which stores the address
of another variable.
Accessing the address of a variable
• The address of operator(&) is used to access the address of a variable.
• Example:
#include<stdio.h>
void main( )
{
int i=5;
printf(“Address of i = %u”,&i);
printf(“Value of i = %d”,i”);
}
• The following uses of & operator are not allowed.
1. &125 - can’t be applied on constants.
2. int x[10];
&x - can’t be applied at array names.
3. &(x+y) – can’t be applied on expressions.
Declaring pointer variables
• Every variable must be declared before its use.
• The declaration of a pointer variable takes the following
form :
• datatype *pointer name;
• E.g. int *ptr;
• It declares ptr as a pointer variable that points to an integer
type. ptr can store the address of an integer variable. It can’t
store the address of a float variable or character variable.
• float *ptr1;
char *ptr2; - ptr2 stores the address of a character variable.
int *ptr;
int i=10;
ptr = &i;
can be written as
int i=10;
int *ptr = &i; - initialization of pointer variable.
or
int i , *ptr=&i;
But the following statement is not valid.
int *ptr=&i , i;
• We can define a pointer variable with an initial value of NULL or 0.
int *ptr = NULL;
int *p = 0;
• However , no other constant value (absolute address) can be assigned to
a pointer variable.
int *p = 5360; - Not allowed.
• We can make the same pointer to point to different data variables.
int x,y,z,*ptr;
ptr = &x;
.
.
ptr = &y;
.
.
ptr = &z;
• We can use different pointers to point to the same data variable.
int x;
int *p1 = &x;
int *p2 = &x;
int *p3 = &x;
Accessing a variable through its pointer
• The value of a variable using the pointer can be accessed
by unary operator(*) known as indirection operator /
value at address operator / dereferencing operator.
• It gives the value stored at a particular address.
int a,b,*ptr;
a=10;
ptr=&a;
b=*ptr; - This statement assigns 10 to b.

i.e. 10 can be referred as value at address contained in


ptr.
#include <stdio.h> i j

void main( ) 3 5000

{ 5000 5010

int i=3;
int *j;
j = &i;
printf(“Address of i = %u”,&i);
printf(“Address of i = %u”,j);
printf(“Address of j = %u”,&j);
printf(“value of j = %u”,j);
printf(“value of i = %d”,i);
printf(“value of i = %d”,*j);
printf(“value of i = %d”,*(&i) );
}
Chain of pointers
• It is possible to make a pointer to point to another
pointer.
• A variable that is a pointer to a pointer must be declared
as follows.
• datatype **pointername;
• E.g. int **ptr;
• This declaration tells the compiler that ptr is a pointer to a
pointer of int type.
#include <stdio.h> a p1 p2

100 5000 5050


void main( )
{ 5000 5050 6000

int a, *p1,**p2;
a = 100;
p1 = &a;
p2 = &p1;
printf(“value of a = %d”,**p2);
}
Now , a can be accessed by
i. a
ii. *(&a)
iii. *p1
iv. **p2
Pointer Expressions / Arithmetic
• Like other variables , pointer variables can be used in
expressions.
• E.g. int *p1 , *p2;
int a = 5 , b=10 ,c;
p1 = &a;
p2 = &b;
c = *p1 + *p2;
• A pointer can be incremented. When we increment a
pointer , its value is increased by the length of the
datatype that it points to . This length is called the scale
factor.
i.e. everytime a pointer is incremented , it points to the
immediately next location of its type.
Example:
#include <stdio.h>
void main( )
{
int i = 5, *x;
float j = 2.5 , *y;
char k = ‘c’ , *z;
clrscr();
printf(“value of i = %d \n” , i );
printf(“value of j = %f \n” , j);
printf(“value of k = %c \n” , k);
x = &i;
y = &j;
z = &k;
printf(“original address in x = %u \n” , x );
printf(“original address in y = %u \n” , y );
printf(“original address in z = %u \n” , z );
x++;
y++;
z++;
printf(“New address in x = %u \n” , x );
printf(“New address in y = %u \n” , y );
printf(“New address in z = %u \n” , z );
}
Sample output:
value of i = 5
value of j = 2.500000
value of k = c
original address in x = 1000
original address in y = 5000
original address in z = 6000
New address in x = 1002
New address in y = 5004
New address in z = 6001
• The way a pointer can be incremented , it can be
decremented to point to earlier locations.
The following operations can be performed on a pointer.
• Addition of a number to a pointer.
• E.g. int i =4 , *j , *k;
j = &i;
j = j + 9;
k = j + 3;
• Subtraction of a number from a pointer.
• E.g. int i =4 , *j , *k;
j = &i;
j = j - 2;
k = j - 6;
• Comparison of two pointer variables
• Pointer variables can be compared using relational operators provided both
variables point to objects of same data type. Such comparisons can be useful
when both pointer variables point to elements of same array.

#include <stdio.h>
void main( )
{
int arr[ ] = { 10 , 20 , 30 , 40 , 50 , 60};
int *j, *k;
clrscr();
j= &arr[4] ;
k = (arr + 4); /* k = &arr[0] + 4 */
if ( j == k)
printf( “ The two pointers point to the same location”);
else
printf( “ The two pointers do not point to the same location”);
}
• Subtraction of one pointer from another.
• This is possible provided both variables point to elements of the same array .
The resulting value indicates the number of elements separating the
corresponding array elements.

#include <stdio.h>
void main( )
{
int ar[ ] = { 10 , 20 , 30 , 40 , 50 , 60};
int *i , *j;
clrscr();
i = &ar[1] ;
j = &ar[5];
printf(“%d %d “, j – i , *j - *i);
}

Output:
4 40
• Two pointers cannot be added.
• A pointer variable cannot be multiplied with a constant.
• A pointer variable cannot be divided with a constant.
Pointers and Arrays
• When an array is declared , the compiler allocates a base
address and sufficient amount of storage to contain all
the elements of array in contiguous memory locations.
• The base address is the address of first element of array.
The base address can be obtained by &ar[0] or by just
specifying the array name.
int ar[5] = {10 , 20 , 30 , 40 , 50};

ar[0] ar[1] ar[2] ar[3] ar[4]

10 20 30 40 50
1000 1002 1004 1006 1008
#include <stdio.h>
void main( )
{
int ar[ ] = { 10 , 11 , 12 , 13 , 14};
int i;
clrscr();
for ( i=0 ; i < 5 ; i++)
{
printf(“ \n Address = %u” , &ar[i]);
printf(“ \n Element = %d” , ar[i]);
}
}
• The previous program can be done using pointers.
#include <stdio.h>
void main( )
{
int ar[ ] = { 10 , 11 , 12 , 13 , 14};
int i ,*j;
clrscr();
j = &ar[0]; /* j = ar; */
for ( i=0 ; i < 5 ; i++)
{
printf(“ \n Address = %u” , j);
printf(“ \n Element = %d” , *j);
j++;
}
}
It is also possible to avoid the loop control variable i as follows.
j = ar;
while ( j <= &ar[4] )
{
printf(“%d” , *j);
j++;
int num[6] = { 11 , 22 , 33 , 44 , 55 , 66};
• Just by mentioning num , we get the base address.
• *num gives the first element of the array i.e. 11.
• *num or *(num+0) refer to 11.
• *(num + 1) gives the second element of the array i.e. 22.
• i.e. num[i] is internally converted to * (num + i ).
• num[i] , *(num + i) , *(i+num) , i[num] refers to the same element.
Pointers and Strings
char str[6] = “Hello”;
• We can store Hello at some location in memory by compiler and assign the
address of the string in a char pointer.
• char *p = “Hello”;

void main( )
{
char str1[ ] = “GOOD”;
char str2[10];
char *s = “Hello”;
char *q;
str2 = str1; /* error.(We can’t assign a string to another string) */
q = s; /* allowed (We can assign a char pointer to another char pointer.) */
printf(“%s” ,q);
puts(s); /* s is a pointer to the string . It is also the name of the
string . Therefore no need to use the indirection operator. */
}
• Once a string has been defined , it cannot be initialized to
another set of characters. But such an operation is
perfectly valid with char pointers.

void main( )
{
char str1[ ] = “Hello”;
char *p = “Hello”;
str1 = “Bye”; /* error */
p = “Bye”; /* works */
}
Write a program using pointers to determine the length of a character
string.
#include <stdio.h>
void main( )
{
char *str , *str1;
int length;
str = “ODISHA”;
str1 = str;
while(*str1 != ‘\0’)
{
printf(“%c is stored at address %u \n”, *str1 ,str1);
str1++;
}
length = str1 – str;
printf(“Length of the string :%d”, length);
}
Array of Pointers
• Array of pointers is a collection of addresses.

void main( )
{
int *arr[4]; /* array of 4 integer pointers */
int i = 3, j =4 , k=5 , l=6 ,m;
arr[0]= &i;
arr[1]= &j ;
arr[2]= &k;
arr[3]= &l;
for (m=0; m <4; m++)
{
printf(“%d “,*(arr[m]) );
}
}
• An array of pointers can even contain the addresses of
other arrays.
• char *name[3] = { “India” , “Australia” , “England”};
• name is declared as an array of three pointers to character
strings.
• Each pointer is pointing to a particular name.
• for(i=0 ; i<3; i++)
printf(“%s\n”, name[i]);
• The character arrays with the rows of varying length are
called ragged arrays and are better handled by pointers.
NULL pointer
• Null pointer is a pointer which is pointing to nothing.
• Incase , if we don’t have any address to be assigned to a
pointer , then we can use NULL.
• Pointer which is initialized with NULL value is called as a
NULL pointer.

#include <stdio.h>
void main( )
{
int *ptr = NULL;
printf(“The value of ptr is :%u”, ptr);
}
Wild pointer
• Uninitialized pointers are known as wild pointers.

void main( )
{
int *ptr;
/* ptr is a wild pointer as it is not initialized yet */
int a = 10;
ptr = &a; /* Now ptr is not a wild pointer */
*ptr = 12;
}
Dangling pointer
• A pointer pointing to a memory location that has been deleted or freed is
called dangling pointer.
• Dangling pointers arise when memory is deallocated without modifying the
value of the pointer . The pointer still points to the memory location of the
deallocated memory.
Deallocation of memory
#include <stdio.h>
#include <stdlib.h>
void main( )
{
int *ptr = (int *) malloc (sizeof(int));
............
............
free(ptr);
/* Now ptr becomes a dangling pointer */
ptr = NULL; /* nomore a dangling pointer */
}
Variable goes out of scope
#include <stdio.h>
#include <stdlib.h>
void main( )
{
char *ptr = NULL;
............
............
{
char ch;
ptr = &ch;
}
.............
............. /* ptr is now a dangling pointer */
}
• Pointer variable ptr is pointing to ch declared in the inner block.
• As character variable ch is nonvisible in outer block , pointer is still pointing to
same invalid memory location in outer block , then pointer becomes dangling.
Generic pointer
• When a pointer variable is declared as a pointer to type
void , it is known as a generic pointer.
• E.g. void *p; /* p becomes a generic pointer */
• A generic pointer can be assigned a pointer value of any
basic datatype.
int *ip;
void *p;
p = ip;
• Generic pointers are useful to point to data of different
types at different times.
void main( )
{
int i;
char c;
void *ptr;
i =5;
c =‘a’;
ptr = &i;
printf(“ptr is pointing to %d” , *(int *)ptr);
ptr = &c;
printf(“ptr is pointing to %c” , *(char *)ptr);
}
• Generic pointers cannot be dereferenced. Since we cannot have a variable
of type void , the pointer will not point to any data and therefore cannot be
dereferenced.
• A generic pointer cannot be directly dereferenced but it can however be
done using typecasting the void pointer.
• Pointer arithmetic is not possible on generic pointers.

You might also like