UMBC CMSC202, Computer Science II, Fall 1998,
Sections 0101, 0102, 0103, 0104
10. Void * and Function Pointers
Thursday October 01, 1998
Assigned Reading: 5.8-5.13
Handouts (available on-line):
Programs from this lecture.
- Briefly discussed the second implementation of the BString class that
fixes some of the problems with the first implementation. (See header file and implementation.)
- New topic: pointers to functions. Each function in C/C++ eventually
gets compiled into machine code and this code gets "loaded" somewhere in
the systems memory. Thus, we can also refer to the address of a function
--- which really turns out to be the address of the first machine
instruction for that function. This address can be stored in a function
pointer. When we use a pointer to point to a variable, the pointer keeps
track of two things: the address of the variable and the type of the
variable. Similarly, a function pointer keeps track of the address of a
function and the type of the function. The type of a function consists of
the types of its parameters and the type of its return value. Do not
confuse the type of a function with the signature of a function, which is
used to resolve function calls for overloaded functions.
- We mentioned above that a pointer keeps track of two things: an
address and the type of the object at that address. We can tell the
compiler to "forget" about the type of the object that a pointer is
pointing to by storing the address in a pointer of type void *.
A pointer of any type can be assigned to a void * pointer,
either by an assignment statement or by passing the pointer to a
function with a void * pointer as a formal parameter.
- Some programs using function pointers and void *
- In the first program, we have 2
functions add3() and add5() with the same type. They
both take an integer parameter and return an integer parameter. This
program shows how to declare a function that takes a function parameter and
how to declare a function pointer to point to add3() and
add5(). Note that a function can be called through a pointer to
that function. See sample run.
- The second program is a variation
of the first. In this case, the functions add3() and
add5() each takes an int pointer parameter.
See sample run.
- The third program is another
variation. This time add5() takes a double pointer
instead of an int pointer. Now the types of add3() and
add5() are similar but different. One way to declare a function
pointer that can point to either add3() or to add5() is
to declare a pointer to a function that takes a void * parameter.
The sample run shows that the CC
compiler complains about assigning the addresses of add3()
and add5() to such a pointer, but the g++ compiler is happy
with such a program.
- One way to fix the problem with the CC compiler is to declare a
function pointer type. In the fourth
program, we have the following type definition:
typedef void (* FPTR_TYPE) (void *) ;
After such a declaration we can use the typecast operator
(FPTR_TYPE) to change the type of the address of
add3() or add5() and store the address in
the variable fptr. Note that once we force the compiler
to "forget" the type of the function, it becomes our responsibility
to invoke the function with the correct parameter. The
sample run shows the consequences if
we call add5() with a pointer to an int variable instead
of a double variable: the contents of the variable n
- Using function pointers, we can write a generic selection sort
function that can sort an array of any type. The function requires
a pointer to a comparison function that will tell it how to compare
two items in the array. The function must also know the number of
elements in the array and the size of each element. The function uses
the bcopy() function to swap "raw" bytes around. Using
this function we can sort arrays of int, double
and even strings. Note that the sort function does not have to be
recompiled to achieve this effect.
- We quickly glossed over an example of using pointers to functions to
design a "generic" queue class, GenQ. In this example, the constructor of
the GenQ class accepts two function pointers: cmp_func and
prt_func. These functions allow the member functions of the GenQ
class to compare two items stored in the queue and to print out an item
stored in the queue. Otherwise, the standard queue operations do not depend
on the data type of the item stored in the queue. Thus, we can use a
void * pointer to point to each item. The test programs (not
presented in class) show that we can use the GenQ class to build a queue of
integers as well as a queue of strings.
29 Oct 1998 17:14:03 EST
to Fall 1998 CMSC 202 Section Homepage