7 Pointers
7 Pointers
Chapter 11 - Pointers
Narasimhan T.
11.1 Introduction
Computer’s memory is a sequential collection of locations where each location can store 1 byte
of data. To distinguish among the locations, the locations are assigned unique addresses starting
from 0 to a maximum value that depends on the size of memory. Say, you have a 4GB (232
bytes) memory, then the addresses vary from 0 to 4294967295 (which is 232 − 1). When you
declare a variable, sufficient amount of memory is allocated for it depending on its type. For
example, an int variable takes 4 bytes. Thus to store an int value, you need 4 locations in
memory and typically 4 contiguous locations are allocated.
0
1
2
..
.
1004
1005
1006 45 a
1007
..
.
..
.
4008 A c
..
.
..
.
8190
8191
Assume we have a hypothetical computer with just 8KB memory. The locations are
assigned addresses from 0 to 8191 as shown in Figure 11.1. Now suppose we have the following
statements in a program:
1
int a = 45;
char c = 'A';
While executing these instructions, 4 bytes of memory (say locations 1004 to 1007) will be
allocated by the system for the variable a and the value 45 will be stored over these locations.
Similarly, for the variable c, one byte (say location 4008) will be allocated and the character ’A’
is stored in it. The address of a variable is the address of the first location in the set of locations
allocated to it. Thus, with the memory map as shown in Figure 11.1, address of a is 1004 and
that of c is 4008.
Now, the addresses are numbers (typically unsigned integers). So they can be stored in
some variable. To make things clear, let us store the address of a in another variable, say p. Thus
p contains the address of a and we say p points to a or p refers to a or p references
a. Such variables that store a memory address (typically location of some other variable) are
called pointer variables or simply pointers. Here p is a pointer variable.
where type is the data type of the pointer and pname is a pointer variable. The data type
of a pointer will be the data type of the variable whose address it stores. With the previous
discussion, p stores the address of a, thus the data type of p is int. (type of a). Thus you
declare p as
int *p;
Once a pointer variable is declared, you can store the address of a variable in it. To get the
address of any variable, C provides the & operator which is called reference operator or address
of operator. Thus to store the address of a in p, you write
p=&a;
One point to note is that the data types of the pointer and that of the variable whose address
is stored in the pointer should match. The following code will yield you an error for the fact
just mentioned.
int a;
float *fp;
fp=&a;
The format specifier to print address is %p. Thus to print the address of a, you write
printf("The address of variable a is %p",&a);
This will print the address in hexadecimal format.
2
int a,*p;
p=&a;
Thus p points to a. Now you can print a’s value using p. For this you use the * operator which
is called dereferencing operator or value at operator. Thus the statement
printf("%d", *p);
will print the value of a. The * operator is powerful in that you can use to change the value
stored at a particular location. See the example below.
Example 11.1. This example illustrates how you can use * operator to change the value at a
location.
int a,*p;
a=45;
p=&a;
printf("The value of a is %d\n",*p);
*p=25;
printf("The value of a now is %d\n",*p);
This code outputs
The value of a is 45
The value of a now is 25
11.4.1 Addition
Assume you have a pointer variable p. To add a constant k to p, you add k × n to p, where n
denotes the size of the data type of p. The following example should make the ideas concrete.
3
1. Only a constant can be added to a pointer variable.
Value of pointer
Expression
Initial value Final value
4014
iptr+3 4008
( = 4008 + 3 × 4)
100A
dptr+1 1002
( = 1002 + 1 × 8)
11.4.2 Subtraction
To subtract a constant k from a pointer p, you subtract k × n from p, where n denotes the size
of the data type of p. See Example below:
Value of pointer
Expression
Initial value Final value
1000
iptr-2 1008
( = 1008 − 2 × 4)
4002
cptr-4 4006
( = 4006 − 4 × 1)
Subtraction operation is not commutative, i.e., ptr - 5 and 5 - ptr are not equivalent.
Moreover, the second case : subtraction of pointer from a constant is not permitted.
Two pointers of same type can be subtracted. Let p1 and p2 be two pointers of same type. To
p1 − p2
subtract p2 from p1, you perform , where n denotes the size of the data type of p1 or
n
p2. The operation is meaningful only if the pointers point to elements of same array. In this
case, the result of the operation is the difference between the subscripts of the two elements. In
other words, the result denotes the number of elements between the pointers.
4
p1 p2
5
11.4.4 Relational operators
A pointer can be compared with another pointer of same type or with zero. It cannot be
compared with any non-zero constant. The result of comparison is either 0 (FALSE) or 1
(TRUE).
Example 11.7. Assume you have the statements in a program
float *p1,*p2;
int p,q,r;
p=p1!=p2;
q=p1==0;
r=p1>p2;
If p1 has the value 4000 and p2 has 4008, the values of p, q, r will be
p = 1, q = 0, r = 0
Note:
6
Pointer Variable
address value
Single indirection
Multiple indirection
Figure 11.3: Single and multiple indirection
Example 11.9. This example exploits the concept that array name denotes the base address,
to input and print array elements.
#include<stdio.h>
main()
7
{
int a[10],n,i;
printf("How many elements you want?\n");
scanf("%d",&n);
printf("Enter the elements\n");
for(i=0;i<n;i++)
scanf("%d",a+i);
printf("The array elements are\n");
for(i=0;i<n;i++)
printf("%d ",*(a+i));
}
Example 11.10. This program finds the length of a string using pointers.
#include<stdio.h>
main()
{
char *cptr,str[10];
int length=0;
printf("Enter the string\n");
scanf("%s",str);
cptr=str; //pointer to first character in the string
while(*cptr!='\0')
{
length++;
cptr++; /*incrementing the pointer so that it points to
next character in the string*/
}
printf("The length of the string %s is %d\n",str,length);
}
8
base address of its zeroth 1D array. In general, x[i] is the base address of ith 1D array of a
2D array x. Equivalently *(x+i) gives the base address of ith 1D array in a 2D array x.
If x[i] is the base address of ith 1D array, then x[i]+j should give you the address of jth
element of ith 1D array. In other words, x[i]+j is the address of the element x[i][j]. Thus
&x[i][j] and x[i]+j are equivalent. Moving on, *(x[i]+j) should then give the value of the
element x[i][j]. Now x[i] and *(x+i) are equivalent. So *(*(x+i)+j) should also give the
value of x[i][j]. Thus the following expressions are equivalent and will print the value of
x[i][j].
⇒ x[i][j]
⇒ (*(x+i))[j]
⇒ *(x[i]+j)
⇒ *(*(x+i)+j)
Example 11.11. This program inputs and prints a 2D array using pointers.
#include<stdio.h>
main()
{
int a[5][5],m,n,i,j;
printf("How many rows?\n");
scanf("%d",&m);
printf("How many columns?\n");
scanf("%d",&n);
printf("Enter the elements\n");
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",a[i]+j);
printf("The array elements are\n");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
printf("%d ",*(a[i]+j));
printf("\n");
}
}
9
parr[2] = &var;
To find the value of var, you write
*parr[2]
An array of pointers can be used to point to an array of data items with each element of the
pointer array pointing to an element of the data array. This is depicted in Figure 11.4. darr
is the int array {55, 457, 25, -874, 0}. parr is a pointer array with the elements pointing
to the elements of darr. Thus each element in parr stores the address of an element in darr.
The elements in darr can be accessed either directly through their subscripts, or indirectly by
dereferencing the elements of the pointer array parr. See Example 11.13.
Example 11.13. This example illustrates how to access the elements of a data array using an
array of pointers.
#include<stdio.h>
main()
{
int darr[10],i,n;
int *parr[10];
printf("How many elements?\n");
scanf("%d",&n);
printf("Enter the elements\n");
for(i=0;i<n;i++)
{
scanf("%d",&darr[i]); //Inputting the array element
parr[i]=darr+i; //Storing the address of array element in pointer array
}
printf("The array elements are \n");
for(i=0;i<n;i++)
printf("%d ",*(parr[i]));
}
Pointer arrays are often used to handle table of strings much effectively. Assume you need
10
darr 55 457 25 -874 0
6000 6004 6008 600C 6010
to store the strings “India”, “Singapore”, “USA”, “UK”, “Japan” and “China”. One way is to
declare a 2D char array
char countries[6][10];
The number of rows is 6 to store the names of 6 countries. The size of each row is set to 10 so
as to accommodate the largest string in the list. But this results in huge wastage of memory
space as many strings in the list are very short. To handle situations like this, you can use array
of pointers. Instead of declaring a 2D char array, you declare an array of char pointers. Each
pointer in the array points to a string in the list:
char *countries[6]={"India",
"Singapore",
"USA",
"UK",
"Japan",
"China"
};
Thus countries[0] will point to “India”, countries[1] to “Singapore” and so on. In general
counties[i] points to ith string in the list. This gives you a more precise way to handle the
table of strings. Only sufficient memory enough to store the strings will be allocated resulting
in better utilization of memory.
11
sptr=&acc;
To access the members of a structure using a pointer to that structure, you must use the
-> operator which is called arrow operator. Thus to access accNum, you write
sptr->accNum
The same can be written also as
(*sptr).accNum
although the first notation is more common. This is illustrated in the example below:
Example 11.15. This program illustrates how to access the structure members through a
structure pointer.
#include<stdio.h>
typedef struct
{
char name[25];
int accNum;
float balance;
}account;
main()
{
account acc, *sptr;
sptr=&acc;
printf("Name please\n");
scanf("%s",sptr->name);
printf("Account number please\n");
scanf("%d",&sptr->accNum);
printf("Balance please\n");
scanf("%f",&sptr->balance);
printf("ACCOUNT DETAILS\n");
printf("Name:%s\n",sptr->name);
printf("Account number:%d\n",sptr->accNum);
printf("Balance:%f\n",sptr->balance);
}
12
account acc[2], *sptr;int i;
for(i=0;i<2;i++)
{
printf("CUSTOMER %d\n",i+1);
printf("Name please\n");
scanf("%s",acc[i].name);
printf("Account number please\n");
scanf("%d",&acc[i].accNum);
printf("Balance please\n");
scanf("%f",&acc[i].balance);
}
for(i=0;i<2;i++)
{
sptr=&acc[i];
printf("ACCOUNT DETAILS OF CUSTOMER%d\n",i+1);
printf("Name:%s\n",sptr->name);
printf("Account number:%d\n",sptr->accNum);
printf("Balance:%f\n",sptr->balance);
}
}
13
printf("%c ",*((char*)vptr));
}
The program declares three variables of int, float and char types and a void pointer. When
you assign address of integer to the void pointer, pointer will become integer pointer. When
you assign address of character to the void pointer, pointer will become character pointer. The
point to note is that when you try to print the variable’s value using void pointer, you need
typecasting. void pointer cannot be dereferenced without typecasting as it has no data type on
its own. If the void pointer contains the address of a float variable, then you need to typecast
the pointer to (float*) before printing the variable’s value. Thus the expression *((float*)vptr)
should correctly print the value of the target float variable. ■
14
printf("%d ",*ptr);
ptr = &var2; //Illegal as ptr is a constant pointer
printf("%d ",*ptr);
}
A pointer through which one cannot change the value of variable whose address it contains
is known as a pointer to constant. As expected, trying to change the variable value through
pointer will result in an error.
Example 11.19. In the program, ptr is a pointer to a constant. It points to var. Later when
you try to change the value, you will get an error.
#include<stdio.h>
main()
{
int var = 20;
const int * ptr = &var; /* This is how you declare a pointer to a
constant */
*ptr = 10; // Illegal. You cannot change the value of var through ptr
printf("%d", *ptr);
}
You have seen constant pointer and pointer to a constant. The next question would be
“Can I have a constant pointer to a constant?”. The answer is YES. A constant pointer to
constant is a pointer that can neither change the address it contains nor it can change the value
kept at that address. Trying to do either of these will lead you to errors.
Example 11.20. In the program, ptr is a constant pointer to a constant. It first points to
var1. Trying to change the value of var1 through ptr is illegal. Similarly, when you try to
point it to var2, you will get an error as it is already pointing to var1.
#include<stdio.h>
main()
{
int var1 = 10,var2 = 20;
const int * const ptr = &var1; // ptr is a constant pointer to a constant
*ptr = 15; // Illegal
ptr = &var2; // Illegal
printf("%d\n", *ptr);
}
15
char title[25];
int edition;
float price;
}book;
main()
{
book b[5], *sptr[5];int i;
for(i=0;i<5;i++)
{
printf("BOOK %d\n",i+1);
printf("Title please\n");
scanf("%s",b[i].title);
printf("Edition please\n");
scanf("%d",&b[i].edition);
printf("Price please\n");
scanf("%f",&b[i].price);
}
for(i=0;i<5;i++)
sptr[i]=&b[i];
for(i=0;i<5;i++)
{
printf("DETAILS OF BOOK%d\n",i+1);
printf("Title:%s\n",sptr[i]->title);
printf("Edition:%d\n",sptr[i]->edition);
printf("Price:%f\n",sptr[i]->price);
}
}
16