views:

140

answers:

5

Possible Duplicate:
What is the point of function pointers?

can anyone explain what function pointers are and why they are needed in layman terms. In c context please?

+2  A: 

Under the hood, a function is just a location in the binary machine code of your program. When you use functions in C, the compiler produces instructions that jump to that particular location after passing in the function's arguments.

A function pointer is a variable you can use to hold the location of a function. This allows one part of your code to determine what function is used in another part of your code. For example, the qsort function takes a function pointer that you use to determine the order of the objects being sorted.

Cogwheel - Matthew Orlando
so you dont know which fuction to call in runtime and you do some type of comparison and call the appropriate function. am I right?
begsor12
I think you have the gist of it. For example, with qsort, you could choose either ascending or descending order based on user input.
Cogwheel - Matthew Orlando
A: 

A function pointer is just like any other pointer, except it points to a function (code).

There are many uses - for example, you could implement message handlers for a network protocol by using a table of structures, each containing a pointer to a handler function, and other associated data to identify each message. Then when a message is received, you can look up the appropriate function and call it via the table's pointer.

Justin Ethier
so you dont know which fuction to call in runtime and you do some type of comparison and call the appropriate function. am I right?
begsor12
A: 

Take a look here - this question has been answered well in another thread.

Will A
A: 

Function pointers point to the binary section of code for a particular function.

The only time I've ever used them was with pthreads. When you launch a thread, you need to tell it where to begin executing, so you would give it a pointer to the function that it should start executing in. In essence, that function becomes the "main()" for the thread, and once it returns from that function, the thread dies.

Without function pointers, there's no way for you to tell pthreads where to begin execution for a new thread.

Phil
+1  A: 

Pointers are the addresses of memory.

A function pointer the address in memory where the code for a function starts.

Often, you know at compile time what function you want to call, so you refer to it by name. When the code si compiled, teh compiler replaces that name with the (usually relative) address of the actual machine code.

But sometimes you don't know what function you want to call at compile time. You could use a switch or something to call different functions:

switch(c) {
  case '+' : add( op1, op2); break;
  case '*' : multiple( op1, op2); break;
  case '/'  : divide(op1, op2); break;
}

but this is tedious and error-prone.

Or you may be writing a library function, like qsort, that knows how to sort any type, but that requires a comparator function to do the sorting. So that we don't have to open up and recompile qsort, qsort allows us to pass it the of the code -- that is, the function -- that we want it to use to compare our user-defined type.

So C (and C++) allow the address of that code -- the address of the function -- to be taken. Taking the address yields a value of type pointer to function (actually, of type pointer to function of type, where the type of the function's signature -- that is, the type and number of its parameters -- and its return type, the type of object it returns. (Note that the signature doesn't include the return type, but the type of the function includes both signature and return type.)

Anyway, this yielded value can of course be assigned to a variable of compatible type -- a pointer to a function, and passed around or copied like any other variable, as after all it's just a number, an address in memory.

So given that we have a function foo, with return type int and signature const void*, const void*:

 int foo( const void* lhs, const void* rhs);

we can create a variable of that type:

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

Yes, really, that's a variable declaration! Read that as "foopointer is a pointer to a function taking two const void pointers and returning int", by reading the name ("foopointer") then left to the pointer ("*"), then right to the parens ("const void*, const void*)", then back left to the int that it returns. The first set of parens are necessary to prevent this from declare a function that returns a pointer-to-int.

Then we can assign the address of our function foo to our variable foopointer, using the address-of operator ("&"):

  foopointer = &foo;

Actually the address-of operator isn't strictly neccessary, and is implied if we don't use it, but use it to make it clear that you're taking an address. It helps readers.

Then we can use foopointer, say to call qsort:

  int some_array_of_int[] = { 1, 3, 2 ) ;
  qsort( some_array_of_int, 
        3 /* elements */, 
        sizeof(int) /*each element is how big?*/, 
        foopointer) ;

Of course, we could just use foo directly: qsort( some_array_of_int, 3 /* elements */, sizeof(int) /each element is how big?/, foo) ;

Either way, qsort will now use foo to compare the numbers in our array, in order to sort them. (A comparator function should return specific values to allow that to happen, which is beyond the scope of this discussion, but in general, *lhs - *rhs).

Now we haven't specified how foo sorts things, but we don't have to in order to reverse how it sorts, as to do that we can just return the negation of foo's return value :

 int reverse_foo( const void* lhs, const void* rhs) {
    return - foo( lhs, rhs ) ;
 }

Now we can decide at runtime whether to sort or list ascending or descending:

  bool reverse = get_reverse_from_user_or_somthing();

  qsort( some_array_of_int, 
         3 /* elements */, 
         sizeof(int) /*each element is how big?*/, 
         reverse ? reverse_foo : foo ) ;

Whoever wrote qsort had no idea how you'd write foo (and reverse_foo), and you had (possibly) no way to re-compile qsort to let it know about foo (or reverse_foo). But thanks to function pointers, qsort can call foo despite the two functions being written years apart, by different coders.

tpdi
thank you very much sir.
begsor12