Dynamic Memory Allocation means to grab storage at run time. Until this point, we had to request memory at compile time. To use the dynamic memory allocation functions below, you must   #include<stdlib.h> For an animated pointer demo, go to   fun with Binky   (thanks to Chris Johnson).
malloc(), calloc(), realloc(), and free()
syntax (form)
pointer_variable = (cast)malloc(#bytes);
We must cast the returned pointer since malloc()
returns a
pointer of type void
.
Example 1
   #include<stdlib.h>
Initially,
 
   int *p1;
   p1 = (int *)malloc(sizeof(int));   // in C++ we have   p1 = new int;
   *p1 = 5;
malloc()
and
*p1 = 5;
_______________   _________________
  int *p2, x;
  p2 = &x;
  *p2 = 5;
p2 = &x;
and *p2 = 5;
_______________ ________________How do examples 1 and 2 differ?
Example
int *ptr;   /*define integer pointer*/
/* get space for integer in heap, assign address
of integer to ptr. */
ptr = (int *)malloc(sizeof(int));
______________ | | Memory for system stack, | | C code, etc. _____ |____________| | | ---> | | |_____| |____________| heap ptr | | |____________|Variable
ptr
holds the address of (points to) the newly created integer.
*ptr = 17; /* store 17 in heap */
______________________________
Since a pointer holds an address, as does an
array name, you can dynamically allocate an entire
array with a single pointer.
/* Allocate an array of 100 floats */
float *fptr; int i;
fptr = (float *)malloc(100 * sizeof(float));
fptr
now points to the first of
100 float values in the heap.
/* Initialize the array to 0.0 */
for(i = 0; i < 100; i++)
  fptr[i] = 0.0;
/* Store 23.8 in 21st element  */
fptr[20] = 23.8;
/* Store 23.8 in 21st element  */
*(fptr+20) = 23.8;
/* Return space for 100 floats to heap */
free(fptr);
scanf("%d", &number);
p = (int *)malloc(number * sizeof(int));
   -and-
scanf("%d", &number);
for(i = 0; i < number; i++)
  p = (int *)malloc(sizeof(int));
NULL
is a constant that is defined in stdlib.h
and is a valid value for a pointer variable.
It means that the pointer is defined, but it holds NULL
(the value hex 0) and
does not point to anything.
Example
Problem:
q is undefined!! int *p = NULL, *q;
if(p == q) puts("Pointers are equal");
NULL
pointers are used to denote the end
of a list or indicate an empty list.
Structure Example
#include<stdio.h>
#include<stdlib.h>
typedef struct data   {
  int x;
  char list[21];   
} DATA_TYPE;
DATA_TYPE *sub(); /* prototype; returns pointer to structure */
main()  
{
  DATA_TYPE *p;
  p = sub();
  printf("value still there %d \n", p->x);
}
Note: We could use (*p).x but p->x is more intuitive.
/* returns address of a structure of type DATA_TYPE */
DATA_TYPE *sub()  
{
  DATA_TYPE *q;
  q = (DATA_TYPE *)    /* cast */
      
malloc(sizeof(DATA_TYPE));
  q->x = 55;
  return(q);
}
    _______     p: |___?___| /* in main() */     _______ ___________     q: |_______| ---->|_55_|_list_| /* in sub() */
inmain()
afterreturn(q);
    _______ ___________     p: |_______| ---->|_55_|_list_| andq
is gone!!!
Notice:
p
and q
are automatic variables.
q->x
is a dynamic variable allocated in the
heap and could be returned to the available space in the heap by:
free(q);
in sub()
-OR-free(p);
in main()
after a call to sub()
free(any_pointer);
 
returns the space to which it points to the heap and the pointer is
then undefined. Now this space can be allocated again.
Notice that the pointer is undefined, not equal to NULL
letter link
struct node { |_???_|__???__|
char letter;
struct node *link;
};
struct node *head, /* pointer to head of list */
*p; /* traveling pointer */
p = (struct node *)malloc(sizeof(struct node));
head = p;
p->letter = 'Z';
p->link = NULL;
p = p->link;
/*Create a linked list with N nodes*/
p = (struct node *)malloc(sizeof(struct node));
head = p; /* one node, 2 pointers */
scanf("%c", p->letter);
for(i = 1; i < N; i++) {
p->link = (struct node *)malloc(sizeof(struct node));
p = p->link; /* Common as i++ */
scanf("%c", p->letter);
}
p->link = NULL;
_________________ |_data__|__link___|
NULL
/* display list */
for(p = head; p != NULL; p = p->link)
    printf("%c\n", p->letter);
NOTE: NULL
is the constant hex 0.(p! = NULL)
can (should?) be written as   (p)
  in a logical expression.
for(p = head; p; p = p->link)
Would pointer-based links be simpler than array-based
links?
- Yes, because the system manages the available
space for you. There is no need for a linked available space list.
If you run out of heap space, malloc()
will return
NULL
. You can test for this easily, but often we don't
worry about it if our space needs are modest.
   #include<stdlib.h>
   int *p;
   p = (int *)malloc(sizeof(int));
   if(p)   *p = 5;
else  {
  puts("heap is full");
  exit(1);
 }
With a pointer-based linked list, we swap pointers (often the link field) when inserting or deleting a node, just as we swapped integer links with an array-based linked list. Just as then, there is no need for excessive data movement.
Questions:
p = booklist; /* point to first element in list */
while(p < = booklist + 99) {
if(p->price == 0.0) {
puts(p->title);
puts("is a freebie!");
puts("");
}
p++; /* advance to next book */
}