Function Pointers in C and C++ - Cprogramming

Embed Size (px)

Citation preview

  • 7/30/2019 Function Pointers in C and C++ - Cprogramming

    1/5

    3/29/13 Function Pointers in C and C++ - Cprogramming.com

    www.cprogramming.com/tutorial/function-pointers.html

    By Alex Allain

    Programs as Data: Function Pointers

    A function pointer is a v ariable that stores the address of a fu nction th at ca n la ter be cal led

    th rough t hat funct ion pointer . This is useful because functions encapsulat e beha v ior. For

    instance, ev ery time y ou need a particular behav ior such as drawing a line, instead of writing

    out a bun ch of code, all y ou n eed to do is call th e function. But som etim es you w ould like to

    choose different behav iors at different t imes in essentia lly th e same piece of code. Read on for

    concrete examples.

    Example Uses of Function Pointers

    Functions as Arguments to Other Functions

    If y ou w ere to writ e a sort r outine, y ou m ight want to allow the function's caller t o choose the order in w hich t he

    data is sort ed; som e progr am m ers migh t need to sort the dat a in ascending order, others mig ht prefer descending

    order wh ile still others ma y wa nt som ethin g similar to but n ot quit e like one of those choices. One wa y to let y our

    user specify w hat to do is to provide a flag a s an arg um ent to the fun ction, but t his is inflexible; the sort funct ionallows only a fixed set of comparison t y pes (e.g., ascending an d descending).

    A m uch nicer way of allowing the user to choose how t o sort th e data is sim ply to let the user pass in a func tion t o

    the sort funct ion. Th is fun ction mig ht take t wo pieces of data a nd perform a compar ison on them . We'll look at t he

    sy ntax for t his in a bit.

    Callback Functions

    An oth er use for funct ion point ers is setting up "listener" or "ca llback" funct ions t hat are in v oked w hen a particula r

    ev ent h appens. The function is called, and this notifies y our code that som ethin g of inter est ha s taken place.

    Why would y ou ev er write code wit h ca llback functions? You often see it when writ ing code u sing someone's

    librar y . One exam ple is wh en y ou're writ ing code for a g ra phical u ser int erface (GUI). Most of the tim e, the user

    will int eract with a loop that al lows th e m ouse poin ter to m ov e and that redraws th e in terface. Sometim es,

    howev er, th e user w ill click on a but ton or ent er text in to a field. These operations are "ev ents" th at m ay requir e a

    response th at y our program needs to handle. How ca n y our code know w hat 's happening ? Using Callback

    functions! The user's click should cause the interface to call a function that you wrote to handle the event.

    To get a sense for w hen y ou m ight do this, consider w hat migh t h appen if y ou w ere using a GUI library that had a

    "creat e_button" funct ion. It migh t ta ke the location wh ere a butt on should appear on the screen, the text of th e

    button, a nd a funct ion to cal l w hen the bu tt on is clicked. Assu m ing for t he m oment that C (a nd C+ +) h ad a

    generic "fun ction pointer " ty pe called func tion, th is m ight look like this:

    void create_button( int x, int y, const char *text, function callback_func );

    Whenev er the bu tt on is clicked, ca llback_func will be in v oked. Exact ly what ca llback_func does depends on the

    button; this is w hy al lowing the create_button function to t ake a funct ion pointer is useful.

    Function Pointer Syntax

    The synt ax for declaring a function pointer m ight seem m essy at first, but in m ost cases it's really quite stra ight-

    forw ar d once y ou understand wh at's going on. Let's look at a simple exa mple:

    void (*foo)(int);

    https://plus.google.com/113987539774523532573?rel=authorhttp://www.cprogramming.com/tutorial/computersciencetheory/sortcomp.htmlhttps://plus.google.com/113987539774523532573?rel=author
  • 7/30/2019 Function Pointers in C and C++ - Cprogramming

    2/5

    3/29/13 Function Pointers in C and C++ - Cprogramming.com

    www.cprogramming.com/tutorial/function-pointers.html

    In th is exam ple, foo is a pointer t o a funct ion ta king one argu m ent, a n integ er, an d that r etur ns void. It's as if

    y ou're decla ring a func tion called "*foo", which ta kes a n int an d returns v oid; now, if *foo is a fu nc tion, th en foo

    mu st be a pointer t o a funct ion. (Sim ilar ly , a declara tion like int *x ca n be read as *x is an int , so x m ust be a

    pointer t o an int .)

    The key to writing the declaration for a function pointer is that y ou're just w riting out the declaration of a

    function but with (*func_nam e) where y ou'd norm ally just put func_nam e.

    Reading Function Pointer Declarations

    Som etim es people get confused when m ore star s are thr own in:

    void *(*foo)(int *);

    Here, th e key is to read inside-out ; notice that the in nerm ost element of th e expression is *foo, an d tha t otherw ise

    it looks like a norm al fun ction declar ation. *foo should refer to a funct ion th at r etur ns a v oid * and takes an int *.

    Consequently , foo is a pointer to just such a funct ion.

    Initializing Function Pointers

    To initialize a funct ion pointer, y ou m ust giv e it th e address of a function in y our program . The sy ntax is like any

    other variable:

    #include

    void my_int_func(int x)

    {

    printf( "%d\n", x );

    }

    int main()

    {

    void (*foo)(int);

    /* the ampersand is actually optional */

    foo = &my_int_func;

    return 0;

    }

    (Note: all exam ples are wr itten to be compatible with both C and C++ .)

    Using a Function Pointer

    To call th e function pointed to by a function pointer, y ou t reat t he function pointer as th ough it w ere the na me of

    the fun ction y ou w ish to call. Th e act of calling it performs th e dereference; th ere's no need to do it y ourself:

    #include void my_int_func(int x)

    {

    printf( "%d\n", x );

    }

    int main()

    {

    void (*foo)(int);

    foo = &my_int_func;

    /* call my_int_func (note that you do not need to write (*foo)(2) ) */

  • 7/30/2019 Function Pointers in C and C++ - Cprogramming

    3/5

    3/29/13 Function Pointers in C and C++ - Cprogramming.com

    www.cprogramming.com/tutorial/function-pointers.html

    foo( 2 );

    /* but if you want to, you may */

    (*foo)( 2 );

    return 0;

    }

    Note that funct ion pointer syn tax is flexible; it can eith er look like most oth er uses of pointer s, with & and *, or y ou

    ma y omit t hat par t of sy ntax. Th is is similar to how ar ray s are treated, where a bare arr ay decay s to a pointer,

    but y ou m ay al so prefix th e array with & t o request its addr ess.

    Function Pointers in the Wild

    Let's go back to th e sorting exa mple w here I sug gested using a fu nction pointer to writ e a generic sorting r outine

    where the ex act order could be specified by the pr ogr am m er ca ll ing the sort ing function. It turns out that th e C

    funct ion qsort does just t hat .

    From t he Linux m an pag es, we ha v e the following declara tion for qsort (from stdlib.h):

    void qsort(void *base, size_t nmemb, size_t size,

    int(*compar)(const void *, const void *));

    Note the use of v oid*s to allow qsort to operate on any kind of data (in C++ , y ou'd norm ally use templates for this

    task, but C++ also allows the u se of v oid* pointer s) because v oid* pointer s can point t o any thin g. Becau se we don't

    know t he size of the individual elements in a v oid* array , we m ust giv e qsort the nu mber of elements, nmem b, of

    the ar ra y to be sorted, base, in addition to the standard requir ement of giv ing th e length , size, of the input.

    But w hat we're really interested in is the compar argu ment to qsort: it's a function pointer t hat takes two void *s

    and retur ns an int. Th is allows any one to specify how to sort t he elements of the arr ay base without ha v ing to

    write a special ized sorting al gor ithm . N ote, al so, that com par returns a n int; the fu nction pointed to should r eturn

    -1 if the first arg um ent is less than t he second, 0 if they ar e equal, or 1 if the second is less th an t he first.

    For insta nce, to sort an a rr ay of num bers in ascending order, we could wr ite code like this:

    #include

    int int_sorter( const void *first_arg, const void *second_arg )

    {

    int first = *(int*)first_arg;

    int second = *(int*)second_arg;

    if ( first < second )

    {

    return -1;

    }

    else if ( first == second )

    {

    return 0;}

    else

    {

    return 1;

    }

    }

    int main()

    {

    int array[10];

    int i;

    /* fill array */

    http://www.cprogramming.com/tutorial/templates.html
  • 7/30/2019 Function Pointers in C and C++ - Cprogramming

    4/5

    3/29/13 Function Pointers in C and C++ - Cprogramming.com

    www.cprogramming.com/tutorial/function-pointers.html

    for ( i = 0; i < 10; ++i )

    {

    array[ i ] = 10 - i;

    }

    qsort( array, 10 , sizeof( int ), int_sorter );

    for ( i = 0; i < 10; ++i )

    {

    printf ( "%d\n" ,array[ i ] );

    }

    }

    Using Polymorphism and Virtual Functions Instead of FunctionPointers (C++)

    You ca n often av oid the need for explicit function pointers by using v ir tu al func tions. For inst an ce, y ou could

    write a sort ing rout ine that ta kes a pointer to a cla ss th at prov ides a v ir tual funct ion c al led com pare:

    class Sorter

    {

    public:

    virtual int compare (const void *first, const void *second);

    };

    // cpp_qsort, a qsort using C++ features like virtual functions

    void cpp_qsort(void *base, size_t nmemb, size_t size, Sorter *compar);

    inside cpp_qsort , w henev er a comparison is needed, compar ->compa re should be called. For classes that ov err ide

    this v irtua l function, the sort routine will get th e new behav ior of that function. For instance:

    class AscendSorter : public Sorter

    {

    virtual int compare (const void*, const void*)

    {

    int first = *(int*)first_arg;

    int second = *(int*)second_arg;

    if ( first < second )

    {

    return -1;

    }

    else if ( first == second )

    {

    return 0;

    }

    else{

    return 1;

    }

    }

    };

    and t hen y ou could pass in a pointer t o an instan ce of th e AscendSort er t o cpp_qsort to sort integer s in ascending

    order.

    But Are You Really Not Using Function Pointers?

    Vir tu al fu nc tions are im plem ented beh ind the scen es using function pointers, so y ou r eally ar e using func tion

  • 7/30/2019 Function Pointers in C and C++ - Cprogramming

    5/5

    3/29/13 Function Pointers in C and C++ - Cprogramming.com

    www.cprogramming.com/tutorial/function-pointers.html

    pointer s--it just h appens that t he compiler m akes the work easier for y ou. Using poly m orphism can be an

    appropriate strat egy (for instan ce, it's used by Jav a), but it does lead to th e ov erhead of ha v ing to create an object

    rath er tha n simply pass in a function pointer.

    Function Pointers Summary

    Syntax

    Declaring

    Declare a funct ion pointer a s th oug h y ou w ere declaring a fu nction, except wit h a na me like *foo instead of just

    foo:

    void (*foo)(int);

    Initializing

    You ca n get th e address of a fu nction sim ply by na m ing it :

    void foo();

    func_pointer = foo;

    or by prefixing th e nam e of the function w ith an am persand:

    void foo();

    func_pointer = &foo;

    Invoking

    Inv oke the func tion pointed to just as if y ou w ere callin g a fun ction.

    func_pointer( arg1, arg2 );

    or y ou may optionally dereference th e function pointer before callin g th e function it points to:

    (*func_pointer)( arg1, arg2 );

    Benefits of Function Pointers

    Function pointer s prov ide a way of passing a round instru ctions for how to do som ethin g

    You ca n write flexible fu nc tions and librar ies that allow t he pr ogr am m er to choose beh av ior by passing

    function pointers as arg um ents

    This flexibility can a lso be achiev ed by using classes with v irtua l functions

    I am grateful to Alex Hoffer and Thomas Carriero for their comments on a draft of this article.

    Related art icles

    Lam bda functions in C++ 1 1 , a replacement for funct ion pointers

    What ar e Pointers?

    Functors in C++, a better funct ion pointer

    http://www.cprogramming.com/tutorial/functors-function-objects-in-c++.htmlhttp://www.cprogramming.com/tutorial/lesson6.htmlhttp://www.cprogramming.com/c++11/c++11-lambda-closures.html