Pointers
Pointers
A pointer is a variable that holds address (memory location) of another variable rather than
actual value. Also, a pointer is a variable that points to or references a memory location in which
data is stored. Each memory cell in the computer has an address that can be used to access that
location. So, a pointer variable points to a memory location and we can access and change the
contents of this memory location via the pointer. Pointers are used frequently in C, as they have a
number of useful applications. In particular, pointers provide a way to return multiple data items
from a function via function arguments.
Pointer Declaration
Pointer variables, like all other variables, must be declared before they may be used in a C
program. We use asterisk (*) to do so. Its general form is:
ata-type *ptrvar;
For example,
int* ptr;
This statement declares the variable ptr as a pointer to int, that is, ptr can hold address of an
integer variable.
Once we declare a pointer variable we can point by it to something. We can do this by
assigning to the pointer the address of the variable you want to point as in the following
example:
int var=11,*ptr;
ptr=&var;
This places the address where var is stores into the variable ptr. For example, if var is stored in
memory 21260 address then the variable ptr has the value 21260.
We can access the contents of the variable pointed by pointer using an asterisk (*) in front of
a variable name. For example,
int var=11,*ptr;
ptr=&var;
*ptr=45; //It changes the value of var to 45
Example:
#include<stdio.h>
#include<conio.h>
void main() {
int var=11,*ptr;
clrscr();
printf("%d\n",var); //prints 11
printf("%d\n",&var); //prints address of var
printf("%d\n",*&var); //prints 11
ptr=&var;
printf("%d\n",ptr); //prints address of var
printf("%d\n",*ptr); //prints 11
*ptr=45;
1
printf("%d\n",var); //prints 45
printf("%d\n",*ptr); //prints 45
getch();
}
The operator ‘&’ is called “address of” operator. The expression &var returns the address of the
variable var. The operator ‘*’ called “value at address” operator. It gives the value stored at a
particular address. The “value at address” operator is also called “indirection operator”.
Passing (call) by Value and Passing (call) by Reference
Arguments can generally be passed to functions in one of the two ways:
o Sending the values of the arguments (pass by value)
o Sending the addresses of the arguments (pass by reference)
Pass by value: In this method, the value of each of the actual arguments in the calling function is
copied into corresponding formal arguments of the called function. With this method the changes
made to the formal arguments in the called function have no effect on the values of actual
arguments in the calling function. The following program illustrates ‘call by value’.
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b;
void swap(int, int );
clrscr();
a = 10;
b = 20;
swap(a,b);
printf("a = %d\tb = %d",a,b);
getch();
}
void swap(int x, int y)
{
int t;
t = x;
x = y;
y = t;
printf("x = %d\ty = %d\n",x,y);
}
The output of the above program would be
x = 20 y = 10
a = 10 b = 20
Note that values of a and b remain unchanged even after exchanging the values of x and y.
Pass by reference: In this method, the addresses of actual arguments in the calling function are
copied into formal arguments of the called function. This means that using these addresses we
would have an access to the actual arguments and hence we would be able to manipulate them.
The following program illustrates this fact.
2
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b;
void swap(int*, int*);
clrscr();
a = 10;
b = 20;
swap(&a,&b);
printf("a = %d\tb = %d",a,b);
getch();
}
void swap(int *x, int *y)
{
int t;
t = *x;
*x = *y;
*y = t;
printf("x = %d\ty = %d\n",*x,*y);
}
The output of the above program would be
x = 20 y = 10
a = 20 b = 10
Note: We can use call by reference to return multiple values from the function.
Pointers and Arrays
An array name by itself is an address, or pointer. A pointer variable can take different addresses
as values. In contrast, an array name is an address, or pointer, that is fixed.
Pointers and One-dimensional Arrays
In case of one dimensional array, an array name is really a pointer to the first element in the
array. Therefore, if x is a one-dimensional array, then the address of the first array element can
be expressed as either &x[0] or simply x. Moreover, the address of the second array element can
be expressed as either &x[1] or as (x+1), and so on. In general, the address of array element (x+i)
can be expressed as either &x[i] or as (x+i). Thus we have two different ways to write the
address of any array element: we can write the actual array element, preceded by an ampersand;
or we can write an expression in which the subscript is added to the array name.
Since, &x[i] and (x+i) both represent the address of the ith element of x, it would seem
reasonable that x[i] and *(x+i) both represent the contents of that address, i.e., the value of the ith
element of x. The two terms are interchangeable. Hence, either term can be used in any particular
situation. The choice depends upon your individual preferences. For example,
/* Program to read n numbers in an array and display their sum and average */
#include<stdio.h>
#include<conio.h>
#define SIZE 100
void main()
3
{
float a[SIZE],sum=0,avg;
int n,i;
clrscr();
printf("How many numbers?");
scanf("%d",&n);
printf("Enter numbers:\n");
for(i=0;i<n;i++)
{
scanf("%f",(a+i)); // scanf("%f",&a[i]);
sum=sum+*(a+i); //sum=sum+a[i];
}
avg=sum/n;
printf("Sum=%f\n",sum);
printf("Average=%f",avg);
getch();
}
Pointers and Multidimensional Arrays
Since one-dimensional array can be represented in terms of a pointer, a multidimensional array
can also be represented with an equivalent pointer notation. A two-dimensional array, for
example, is actually a collection of one-dimensional arrays. Therefore, we can define a two-
dimensional array as a pointer to a group of contiguous one-dimensional arrays.
Suppose x is a two-dimensional integer array having 10 rows and 20 columns. We can
declare x as
int (*x)[20];
rather than
int x[10][20];
In the first declaration, x is defined to be a pointer to a group of contiguous, one-dimensional,
20-element integer arrays. Thus, x points to the first 20-element array, which is actually the first
row (i.e., row 0) of the original two-dimensional array. Similarly, (x+1) points to the second 20
element array, which is the second row (row 1) of the original two-dimensional array, and so on.
Now, we can access the element in row 2 (third row) and column 5 (sixth column) by writing
either x[2][5] or *(*(x+2)+5). In general, we can access the element in row i and column j by
writing x[i][j] or *(*(x+i)+j). For example,
#include<stdio.h>
#include<conio.h>
#define ROW 3
#define COL 2
void main()
{
int a[ROW][COL],b[ROW][COL],i,j,sum;
clrscr();
printf("Enter elements of first matrix:\n");
for(i=0;i<ROW;i++)
{
4
for(j=0;j<COL;j++)
scanf("%d",(*(a+i)+j));
printf("\n");
}
printf("Enter elements of second matrix:\n");
for(i=0;i<ROW;i++)
{
for(j=0;j<COL;j++)
scanf("%d",(*(b+i)+j));
printf("\n");
}
printf("Addition matrix is:\n");
for(i=0;i<ROW;i++)
{
for(j=0;j<COL;j++)
{
sum=*(*(a+i)+j)+*(*(b+i)+j);
printf("%d\t",sum);
}
printf("\n");
}
getch();
}
Dynamic Memory Allocation
Dynamic memory allocation is the process of allocating memory in a program dynamically at
run time. C provides two basic functions calloc() and malloc() for this purpose. The name calloc
stands for “contiguous allocation” and the name malloc stands for “memory allocation”.
The programmer uses calloc() and malloc() to dynamically create space arrays, structures,
and unions.
The function calloc() takes two arguments both of unsigned integral type. When we call this
function, it allocates contiguous space in memory. For example,
/* Program to read n floating point numbers and display their sum and average using pointer and
dynamic memory allocation*/
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
float *a,sum=0,avg;
int n,i;
clrscr();
printf("How many numbers?");
scanf("%d",&n);
a=(float*)calloc(n,sizeof(float));
printf("Enter numbers:\n");
5
for(i=0;i<n;i++)
{
scanf("%f",(a+i)); //scanf("%f",&a[i]);
sum=sum+*(a+i); //sum=sum+a[i];
}
avg=sum/n;
printf("Sum=%f\n",sum);
printf("Average=%f",avg);
free(a);
getch();
}
In the above program a points to the first memory block in the allocated memory.
The programmer uses malloc() in a similar fashion. This function takes a single argument of
unsigned integral type. For example,
a=(float*)mallocc(n*sizeof(float));
When we use calloc(), the space is initialized with all bits set to zero. Unlike, calloc(), the
function malloc() does not initialize the space in memory that it makes available. In a large
program, malloc() may take less time.
Space that has been dynamically allocated with either calloc() or malloc() does not destroyed
automatically. The programmer must use free() explicitely to destroy it. For example,
free(a);
Operations on Pointers
Not all operations are applied for pointers. Permissible operations that can be applied for pointers
are given below:
1. A pointer variable can be assigned the address of an ordinary variable. For example, pv =
&v, where pv is a pointer variable and v is an ordinary variable.
2. A pointer variable can be assigned the value of another pointer variable provided both
pointers point to objects of the same data type. For example, pv = px, where both pv and
px are pointer variables of the same data type.
3. A pointer variable can be assigned a null (zero) value. For example, pv = NULL, where
NULL is a symbolic constant that represent the value zero and pv is a pointer variable.
4. An integer quantity can be added to or subtracted from a pointer variable. For example,
pv+3, ++pv etc. where pv is a pointer variable.
5. One pointer variable can be subtracted from another provided both pointers point to
elements of the same array.
6. Tow pointer variables can be compared provided both pointers point to objects of the
same data type.
Other arithmetic operations on pointers are not allowed. Thus, a pointer variable cannot be
multiplied by constant; two pointer variables cannot be added; and so on.
Pointer Constant and Pointer to Constant
Pointer constant or constant pointer means the pointer is constant. For example, int *const
ptr2 indicates that ptr2 is a pointer which is constant. This means that ptr2 cannot be made to
point to another integer after it points to some integer. However the integer pointed by ptr2 can
be changed. For example,
6
int a=2,b=3;
int *const ptr2 = &a;
ptr2=&b; //error
It is not a pointer to constant. A pointer to constant is written like
const int *ptr1. It indicates that ptr1 is a pointer that points to a constant integer. The integer is
constant and cannot be changed. However, the pointer ptr1 can be made to point to some other
integer constant. For example,
const int a=2;
const int *ptr2 = &a;
*ptr2=8; //error