Dynamic Memory Allocation
Dynamic Memory Allocation
Allocation
Problem with Arrays
Sometimes
Amount of data cannot be predicted beforehand
Number of data items keeps changing during program
execution
Example: Seach for an element in an array of N elements
One solution: find the maximum possible value of N and
allocate an array of N elements
Wasteful of memory space, as N may be much smaller
in some executions
Example: maximum value of N may be 10,000, but a
particular run may need to search only among 100
elements
Using array of size 10,000 always wastes memory
in most cases
Better Solution
Dynamic memory allocation
Know how much memory is needed after the program
is run
Example: ask the user to enter from keyboard
Dynamically allocate only the amount of memory
needed
C provides functions to dynamically allocate
memory
malloc, calloc, realloc
Memory Allocation Functions
malloc
Allocates requested number of bytes and returns a
pointer to the first byte of the allocated space
calloc
Allocates space for an array of elements, initializes
them to zero and then returns a pointer to the
memory.
free
Frees previously allocated space.
realloc
Modifies the size of previously allocated space.
We will only do malloc and free
Allocating a Block of Memory
A block of memory can be allocated using the
function malloc
Reserves a block of memory of specified size
and returns a pointer of type void
The return pointer can be type-casted to any
pointer type
General format:
type *p;
p = (type *) malloc (byte_size);
Example
p = (int *) malloc(100 * sizeof(int));
1 S o u r a v \0
2 K h a n \0
3 I n d i a \0
9
Pointers to Pointers
Pointers are also variables (storing addresses),
so they have a memory location, so they also
have an address
Pointer to pointer – stores the address of a
pointer variable
p[0]
p int ** int *
p[1] int *
p[2] int *
2D array
#include <stdlib.h>
int main()
{
int **array;
array = (int**) malloc(nrows * sizeof(int *));
{
2D array
Int main()
x 0
{ 1
2
x 3
*x;
*(x+1);
**(x+1); x[1][0]
*(x[3]+7) ???
9
*(*(x+1)+4)
} x[1][4]
*((*x)+8) x[0][8]
Dynamic Allocation of 2-d Arrays
Recall that address of [i][j]-th element is found
by first finding the address of first element of i-
th row, then adding j to it
Now think of a 2-d array of dimension [M][N]
as M 1-d arrays, each with N elements, such
that the starting address of the M arrays are
contiguous (so the starting address of k-th
row can be found by adding 1 to the starting
address of (k-1)-th row)
This is done by allocating an array p of M
pointers, the pointer p[k] to store the starting
address of the k-th row
Contd.
Now, allocate the M arrays, each of N
elements, with p[k] holding the pointer for
the k-th row array
Now p can be subscripted and used as a
2-d array
Address of p[i][j] = *(p+i) + j (note that
*(p+i) is a pointer itself, and p is a pointer
to a pointer)
Dynamic Allocation of 2-d Arrays
int **allocate (int h, int w)
{
void read_data (int **p, int h, int w)
int **p; Allocate array {
int i, j; of pointers int i, j;
for (i=0;i<h;i++)
p = (int **) malloc(h*sizeof (int *) );
for (j=0;j<w;j++)
for (i=0;i<h;i++)
scanf ("%d", &p[i][j]);
p[i] = (int *) malloc(w * sizeof (int));
}
return(p);
}
Allocate array of Elements accessed
integers for each like 2-D array elements.
row
Contd.
void print_data (int **p, int h, int w) int main()
{ {
int i, j; int **p;
for (i=0;i<h;i++) int M, N;
{ printf ("Give M and N \n");
for (j=0;j<w;j++) scanf ("%d%d", &M, &N);
printf ("%5d ", p[i][j]); p = allocate (M, N);
printf ("\n"); read_data (p, M, N);
} printf ("\nThe array read as \n");
} print_data (p, M, N);
return 0;
}
Contd.
void print_data (int **p, int h, int w) int main()
{ {
int i, j; int **p;
for (i=0;i<h;i++) int M, N;
{ printf ("Give M and N \n");
for (j=0;j<w;j++) scanf ("%d%d", &M, &N);
printf ("%5d ", p[i][j]); p = allocate (M, N);
printf ("\n"); read_data (p, M, N);
} Give M and N printf ("\nThe array read as \n");
33
} print_data (p, M, N);
123
456 return 0;
789 }
The array read
as
1 2 3
4 5 6
7 8 9
Memory Layout in Dynamic Allocation
int **allocate (int h, int w)
int main() {
{ int **p;
int **p; int i, j;
int M, N;
printf ("Give M and N \n"); p = (int **)malloc(h*sizeof (int *));
scanf ("%d%d", &M, &N); for (i=0; i<h; i++)
p = allocate (M, N); printf(“%10d”, &p[i]);
for (i=0;i<M;i++) { printf(“\n\n”);
for (j=0;j<N;j++) for (i=0;i<h;i++)
printf ("%10d", &p[i][j]); p[i] = (int
printf(“\n”); *)malloc(w*sizeof(int));
} return(p);
return 0; }
}
Output
Starting address of each
row, contiguous (pointers
33 are 8 bytes long)
31535120 31535128 31535136
}
10 5
x y 10 5
a b
Call by Reference
Int main()
swap(int *a, int *b)
{
{
int x=10, y=5;
swap(&x,&y);
int temp;
temp=*a;
*a=*b;
*b=temp;
}
}
1400 10 5 1500 *b
x y
1400 1500
*a
a b