17. advanced uses of pointers. dynamic storage allocation many programs require dynamic storage...

21
17. ADVANCED USES OF POINTERS

Upload: george-floyd

Post on 31-Dec-2015

221 views

Category:

Documents


3 download

TRANSCRIPT

17. ADVANCED USES OF POINTERS

Dynamic Storage Allocation• Many programs require dynamic storage allocation: the ability to allocate storage as needed during program execution.

• Dynamically allocated storage may be used for any kind of data object.

• The objects most commonly allocated are:ArraysStringsStructures

• Dynamically allocated structures can be linked together to form lists, trees, andother data structures.

The malloc Function• The most important storage allocation function is named malloc. When called, malloc allocates a block of size bytes and returns a pointer to it:void *malloc(size_t size);

• malloc returns a “generic” pointer that is capable of pointing at an object of any type. malloc’s return value can be stored in a variable of any pointer type:int *pi;pi = malloc(sizeof(int)); /* allocate memory for an int */For portability, it is best to use sizeof when calling malloc .

• Memory allocated by malloc is not cleared.

The Null Pointer• When malloc cannot locate a memory block of the requested size, it returns a null pointer.

• The macro NULL represents the null pointer. It is defined in <locale.h>, <stdio.h>, <stdlib.h>, <string.h>, <stddef.h>, and <time.h>;

one of these must be included in any program that uses NULL.

• NULL actually stands for the value 0:#define NULL 0To avoid confusion with the integer 0, it’s usually best to use NULL instead of 0 to represent the null pointer.

The Null Pointer

• Since NULL is equivalent to 0, it tests false in if, while, do, and for statements:int *p;…if (p) … /* true if p is not NULL */

• It is illegal to apply the indirection operator to a null pointer:p = NULL;i = *p; /* illegal */

Dynamically Allocated Strings• malloc is often used to dynamically allocate space for strings.

• malloc is especially useful to allocate space for the result of a string operation:char *result;result = malloc(strlen(s1) + strlen(s2) + 1);strcpy(result, s1);strcat(result, s2);

• Warning: When using malloc to allocate space for a string, don’t forget to include room for the null character.

Dynamically Allocated Arrays• An array can be dynamically allocated by a call of the calloc function.calloc is similar to malloc, but allocates space for an array with nmemb elements, each of which is size bytes long:

void *calloc(size_t nmemb, size_t size);

• The block of memory allocated by calloc is cleared (set to 0 bits).

Dynamically Allocated Arrays• Example:int *a, size, i;printf("Enter array size: ");scanf("%d", &size);a = calloc(size, sizeof(int));printf("Enter array elements: ");for (i = 0; i < size; i++)scanf("%d", &a[i]);

• Warning: A program that uses malloc or calloc must include the following header file:#include <stdlib.h>

If this file is not included, calloc and malloc would be assumed to return int values, causing unpredictable effects.

The free Function• When a block of memory obtained by calling malloc or calloc is no longer referenced by a pointer, it is said to be garbage. In the following example, the memory pointed to by p becomes garbage when p is assigned a new value:

int *p, *q;p = malloc(sizeof(int));q = malloc(sizeof(int));p = q;

Garbage should be avoided; we need to “recycle” memory instead.

The free Function• When a block of memory is no longer needed, it can be released by calling the free function:int *p, *q;p = malloc(sizeof(int));q = malloc(sizeof(int));free(p);p = q;

• Warning: Watch for “dangling pointers” left behind by a call of free:int *p, *q;p = malloc(sizeof(int));q = p;free(p);*q = 0; /* error */

Linked Lists• Dynamic storage allocation is useful for building lists, trees, graphs, and other linked structures.• A linked structure consists of a collection of nodes. Each node contains one or more pointers to other nodes. In C, a node is represented by a structure.• The simplest linked structure is the linked list, which consists of a chain of nodes, with each node pointing to the next node in the chain. A node in a linked list might have the following definition:struct node {int data;struct node *next;};The use of a structure tag is mandatory, since the node structure contains a reference to itself.

Linked Lists• An ordinary pointer variable points to the first node in the list; to indicate that the list is empty, the variable can be assigned NULL:struct node *first = NULL;

The Right Arrow Operator

• Nodes can be created by calling malloc:struct node *temp;temp = malloc(sizeof(struct node));

• The . operator can be used to select the data member in the node that temp points to:(*temp).data = n;

• Because pointers often point to structures, C provides a special notation (the right arrow selection operator) for selecting members of these structures:temp->data = n;

Example: Inserting into a Linked List

• The following statements will create a node containing n, then insert it at the beginning of the list pointed to by first:

struct node *temp;temp = malloc(sizeof(struct node));temp->data = n;temp->next = first;first = temp;

Example: Inserting into a Linked List

• The following example creates a linked list containing numbers entered by the user:struct node *first = NULL, *temp;int n;printf("Enter a series of numbers (enter 0 to stop): ");scanf("%d", &n);while (n != 0) {temp = malloc(sizeof(struct node));temp->data = n;temp->next = first;first = temp;scanf("%d", &n);}The numbers will appear in the list in the reverse of the order in which they were entered.

Example: Searching a Linked List

• The following statement searches a list for an integer n:for (temp = first; temp != NULL; temp = temp->next)if (temp->data == n)… /* found n */

Example: Deleting from a Linked List

• The following statements will delete the first node containing n from the list pointed to by first, assuming that n is present in the list:struct node *p, *q;for (p = first, q = NULL;p != NULL && p->data != n;q = p, p = p->next);if (q == NULL)first = first->next; /* n is at the beginning */elseq->next = p->next; /* n is not at the beginning */free(p);

Functions Passed as Arguments

• C does not allow a function to be passed as an argument to another function. However, a pointer to a function can be passed:int find_zero(int (*f)(int));int poly(int i);int main(void){printf("Answer: %d\n", find_zero(poly));return 0;}int find_zero(int (*f)(int)){int n = 0;while ((*f)(n)) n++; /* or while (f(n)) n++; */return n;}int poly(int i){return i * i + i - 12;}

Functions Passed as Arguments

• Pointers to functions can be used in numerous other ways. For example:A function can return a pointer to a function.A variable can store a pointer to a function.An array may contain pointers to functions.

The qsort Function• Certain functions in the C standard library require a function pointer as a parameter.

One of the most commonly used is qsort, a general-purpose algorithm capable of sorting any array.

• The following declaration for qsort appears in <stdlib.h>:void qsort(void *base, size_t nmemb, size_t size,

int (*compar)(const void *, const void *));base is a pointer to the first element in the array.nmemb is the number of elements in the array.size is the size of each array element.compar is a pointer to a function that compares two array elements.

The qsort Function• When given two pointers p and q to array elements, compar must return a number that is

Negative if *p is “less than” *q.Zero if *p is “equal to” *q.Positive if *p is “greater than” *q.