Logged in as: guest Log in
Lab 8 mcmillan / Version 5

Function Pointers

April 5, 2012


Prelab (complete before lab)

As before, make sure you can access the CS servers.

Part 1: Basic, that is C, syntax

Recall from the homework assignment "Stack Detective" that you could, through investigating the stack, determine where in memory the 'fib' function was located.  Also recall that we can use pointers to variables in order to pass around memory addresses, allowing us to avoid copying the actual data values and structures.  We can do the same thing with the memory addresses of functions, using function pointers. These allow flexible behavior in C programs: you can make code statements of the kind 'use a function with x arguments and y return value here', and only specify which function to actually use during run time!  Function pointers are allso the classic way of implementing callback functions.

One key difference between function pointers and pointers to data types is that you can never "allocate" a new function and assign its address to a pointer.  Instead, you assign the address of some function you have written to a function pointer.

To define a function pointer, you use syntax that is a combination of declaring a function and declaring a variable.  First, list the function return value.  Next, you give the name of the function pointer, but it must be placed in parentheses with an asterix before it.  Finally, you give the argument list in parenthesis and, optionally, an assignment statement.

For exmple, a function that returns a float, and takes in an int argument and a float argument.

    float (*myFuncPointer) (int, float) = NULL;

Now, we can assign a function to this pointer.  For example, if we define 

    float some_func (int a, float b)
    {
        return a * b;
    }

we can assign

    myFuncPointer = &some_func;

Now we can call the function pointer with

    (*myFuncPointer)(4, 5);

Checkoff 1: Write the definition of a function pointer that returns nothing (a.k.a. void) and accepts a string.

Because there is no ambiguity between copying the value of a function and copying its address, there are syntax shortcuts that allow you to skip certain * and &.  These will be left for you to research on your own, if you are interested.

We can use printf to see the address of a pointer.  For example, given the code snippet

    ...
    int a_var = 5;
    float (*myFuncPointer)(int, float) = NULL;
    myFuncPointer = &some_func;
    printf("%p\n", &a_var);
    printf("%p\n", myFuncPointer);
    printf("%p\n", &myFuncPointer);
    ...

could print an output such as 

    0x7fff5fbff48c
    0x100000dba
    0x7fff5fbff480

Checkoff 2: Explain why two of these memory addresses are close to eachother while the third is quite different. 

Part 2: Select your function

We can pass a function pointer to a program as an argument.  To do this, we must include a declaration of a function pointer in the argument list.  For example,

    float takesPointer(float a, float b, float (*passedPointer)(float, float))
    {
        return (*passedPointer)(a, b);
    }

Can be passed a function pointer, of the same type described above, as its third argument.

Consider the following program, modified from lab 5:

    #include <stdio.h>
    
    int a[] = {30, 40, 50, 10, 20};
    
    int compare(int a, int b)
    {
        return a < b;
    }
    
    int min(int array[], int size)
    {
        int i;
        int minIndex = 0;
        int minValue = array[0];
        
        for (i = 1; i < size; i++)
            if (compare(array[i], minValue)) {
                 minValue = array[i];
                 minIndex = i; 
            }
        return minIndex;
    }
    
    void selectionSort(int array[], int N)
    {
        int i, j, t;
        int *p = array;
        
        for (i = 0; i < N-1; i++) {
             j = min(p,N-i);
             t = array[i];
             array[i] = array[i+j];
             array[i+j] = t;
             p += 1;
        }
    }
    
    int main( )
    {
        int i;
    
        for (i = 0; i < 5; i++)
             printf("%d: %d\n", i, a[i]);
        printf("\n");
    
        selectionSort(a, 5);
    
        for (i = 0; i < 5; i++)
            printf("%d: %d\n", i, a[i]);
        printf("\n");
    }
    
    

This selection sort fuction puts the array a in a ascending order.  The order is determined by the compare function, which is used in min().  Note that if you change the less-than sign to a greater-than sign, the sorted list created is in reversed (decending) order.

Checkoff 3: Modify this program so that min uses a function pointer where compare is currently used.  This function pointer should be passed to selectionSort as a third argument, and then on to min.  Then create a new compare function that will result in the array being sorted in reverse order.  Write down your additions to the code, and verify that your new function creates a sorted array in reverse order.

Part 3: Returning to syntax

Though it is not used as often as passing a function pointer as an argument, function pointers can also be returned by functions.  However, the syntax for this is even more complicated (and seemingly arbitrary) than what you have seen so far.  

So let us first look at a helper called typedef.  typedef lets us assign a new name to a complex data type. The usual syntax for typedef is 

    typedef (some data type) (new name);

The syntax for using the typedef with function pointers is to simply say 

    typedef (declaration of the function pointer);

for example, 

    typedef int (*func_pt_type)(char*, float);

creates a new data type, func_pt_type, which is a pointer to a function that returns an integer and takes a string and float as arguments.  We can now use comp_func like a normal data type, including specifying it as a return value, i.e.

    func_pt_type function_to_get_a_function(int a)
    {
        ...
    }

Checkoff 4: Modify the selection sort code above to use a typedef to define a type for the for the function pointer you used.




Site built using pyWeb version 1.10
© 2010 Leonard McMillan, Alex Jackson and UNC Computational Genetics