Function pointer as an argument
Definitely.
void f(void (*a)()) {
a();
}
void test() {
printf("hello world\n");
}
int main() {
f(&test);
return 0;
}
Passing a function pointer with it's own parameters in C
Parameters are not passed. It is arguments that are passed.
So this function declaration
void runner(void (* function)(int in)){
(*function)(in);
}
has only one parameter: a pointer to a function, But if you want to call the pointed function that expects an argument then you need to supply an argument.
In this declaration of a function pointer
void (* function)(int in)
the function parameter in
has the function prototype scope..
You may declare the function parameter without its identifier like
void (* function)(int)
So you have to declare the function with two parameters like
void runner(void (* function)(int), int in ){
function(in);
}
Pay attention to that to dereference the pointer to function is redundant.
All these calls as for example
( *function )( int );
or
( *****function )( in );
are equivalent to
function( in );
Function pointer parameter without asterisk
Standard says that these two functions are equivalent as function arguments are adjusted to be a pointer to function arguments:
16.1 Overloadable declarations [over.load]
(3.3) Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (11.3.5).
same in C:
6.7.5.3 Function declarators (including prototypes)
8 A declaration of a parameter as ‘‘function returning type’’ shall be adjusted to ‘‘pointer to
function returning type’’, as in 6.3.2.1.
How do you pass a function as a parameter in C?
Declaration
A prototype for a function which takes a function parameter looks like the following:
void func ( void (*f)(int) );
This states that the parameter f
will be a pointer to a function which has a void
return type and which takes a single int
parameter. The following function (print
) is an example of a function which could be passed to func
as a parameter because it is the proper type:
void print ( int x ) {
printf("%d\n", x);
}
Function Call
When calling a function with a function parameter, the value passed must be a pointer to a function. Use the function's name (without parentheses) for this:
func(print);
would call func
, passing the print function to it.
Function Body
As with any parameter, func
can now use the parameter's name in the function body to access the value of the parameter. Let's say that func
will apply the function it is passed to the numbers 0-4. Consider, first, what the loop would look like to call print directly:
for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
print(ctr);
}
Since func
's parameter declaration says that f
is the name for a pointer to the desired function, we recall first that if f
is a pointer then *f
is the thing that f
points to (i.e. the function print
in this case). As a result, just replace every occurrence of print in the loop above with *f
:
void func ( void (*f)(int) ) {
for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
(*f)(ctr);
}
}
Source
Function pointer with named arguments?
The names of arguments in a function pointer are optional, just as the names of arguments in a function declaration are optional. This is because parameter names if given are not used, so both formats are allowed.
In section 6.7.6.3 of the C standard regarding Function Declarators, which includes both function prototypes and function pointers, paragraph 6 states:
A parameter type list specifies the types of, and may
declare identifiers for, the parameters of the function.
The only place where function parameters require a name is in the actual definition of a function.
For a function definition, Section 6.9.1p5 states:
If the declarator includes a parameter type list, the
declaration of each parameter shall include an identifier, except
for the special case of a parameter list consisting of a single
parameter of type void , in which case there shall not be an
identifier. No declaration list shall follow.
Passing an argument to function pointer
Since you have an array of function pointers, all the functions need to be of the same type. So at the very least each function should take a const char *
(not all functions need to use it) and the array type should be changed to match.
If you want something more flexible, you can have the functions accept a single void *
so each function can be passed a different parameter which it then casts to the appropriate type. This is how pthreads passes parameters to functions which start a new thread. You will lose some compile-time type checking with this, so be careful if you go this route.
EDIT:
An example of the latter:
#include<stdio.h>
#include<stdlib.h>
int update(void *);
int upgrade(void *);
int quit(void *);
int main(void){
const char *question = "Choose Menu\n";
const char *options[3] = {"Update", "Upgrade", "Quit"};
int (*actions[3])(void *) = {update,upgrade,quit};
show(question,options,actions,3);
return 0;
}
int update(void *unused){
printf("\n\tUpdating...\n");
return 1;
}
int upgrade(void *unused){
printf("\n\tUpgrade...\n");
return 1;
}
int quit(void *message){
printf("\n\tQuit...%s\n", (char *)message);
return 0;
}
void show(const char *question, const char **options, int (**actions)(void *), int length){
...
if (act == quit) {
repeat = act("GoodBye");
} else {
repeat = act(NULL);
}
...
}
How do function pointers in C work?
Function pointers in C
Let's start with a basic function which we will be pointing to:
int addInt(int n, int m) {
return n+m;
}
First thing, let's define a pointer to a function which receives 2 int
s and returns an int
:
int (*functionPtr)(int,int);
Now we can safely point to our function:
functionPtr = &addInt;
Now that we have a pointer to the function, let's use it:
int sum = (*functionPtr)(2, 3); // sum == 5
Passing the pointer to another function is basically the same:
int add2to3(int (*functionPtr)(int, int)) {
return (*functionPtr)(2, 3);
}
We can use function pointers in return values as well (try to keep up, it gets messy):
// this is a function called functionFactory which receives parameter n
// and returns a pointer to another function which receives two ints
// and it returns another int
int (*functionFactory(int n))(int, int) {
printf("Got parameter %d", n);
int (*functionPtr)(int,int) = &addInt;
return functionPtr;
}
But it's much nicer to use a typedef
:
typedef int (*myFuncDef)(int, int);
// note that the typedef name is indeed myFuncDef
myFuncDef functionFactory(int n) {
printf("Got parameter %d", n);
myFuncDef functionPtr = &addInt;
return functionPtr;
}
Call a function using a pointer and pass the pointer that can point to the function along in the parameters
Yes, it's doable.
The simple way:
void (*fptr_t)(void*);
The function pointer is data, even though it point to non-data. Therefore a pointer to function pointer can be converted to void*
without relying on compiler extensions.
This solution lacks type safety. However, it can be improved.
Currently, it is possible to declare a function taking unspecified number of parameters. It allows to form an incomplete function type. For example:
int foo();
declares a function that returns int
and takes unspecified parameters. To have a function taking no parameters use int foo(void)
.
This allows to declare a function taking a pointer to pointer to incomplete function type:
int foo(int (**)());
// call
int (*fptr)(int (**)()) = foo;
fptr(&fptr);
As mentioned in other answers typedef
-ing function types makes the code cleaner.
typedef int foo_aux_f();
typedef int foo_f(foo_aux_f**);
foo_f *fptr = &foo;
fptr(&fptr);
It is possible to improve type safety by nesting the declaration of function types deeper and deeper.
typedef int foo_aux0_f();
typedef int foo_aux1_f(foo_aux0_f**);
typedef int foo_aux2_f(foo_aux1_f**);
typedef int foo_aux3_f(foo_aux2_f**);
typedef int foo_f(foo_aux3_f**);
foo_f fptr = &foo;
fptr(&fptr);
The perfect recursive type would be reached with infinite chain of declaration but in practice 2-3 levels are sufficient.
With some abuse of the syntax of typedef
keyword it is possible to squeeze the declaration of this type:
typedef int foo_aux0_f(),
foo_aux1_f(foo_aux0_f**),
foo_aux2_f(foo_aux1_f**),
foo_aux3_f(foo_aux2_f**),
foo_f(foo_aux3_f**);
Unfortunately ... or fortunately, this trick will likely not work in upcoming C23 because the old function declarations without prototypes are planned to be removed from the language making ()
mean no arguments rather then unspecified number of argument.
C++ Function Pointer as Argument and Classes?
You're not using a regular function pointer for your callback. You're using a non-static member function pointer, so the regular function pointer syntax and calling mechanics aren't going to work. There is a significant difference both in the pointer declaration syntax and the mechanism used for invoking non-static members.
To declare a pointer-to-member function for a member of the Image
class taking no parameters and returning void
, the syntax would be:
void (Image::*function)().
Invoking a member function is done using one of two special operators, ->*
when using an object pointer, or .*
when using an object reference. For example:
// declare a pointer to Image member function
void (Image::*function)();
// assign address of member function
function = &Image::ImageClicked;
// uses ->* for access
Image *pObj = new Image();
(pObj->*function)();
// uses .* for access
Image image;
(image.*function)();
Hope that helps
Related Topics
C++11: "Narrowing Conversion Inside { }" with Modulus
How to Overload Operator==() for a Pointer to the Class
How to Initialize 'Std::Function' with a Member-Function
How Can Duff's Device Code Be Compiled
What Does Iterator->Second Mean
What Are Some Tricks I Can Use with MACros
Is "Long Long" = "Long Long Int" = "Long Int Long" = "Int Long Long"
Difference Between Opening a File in Binary VS Text
How Does Calling Srand More Than Once Affect the Quality of Randomness
Is Static Init Thread-Safe with Vc2010
How to Test Whether Class B Is Derived from Template Family of Classes
Forcing String to Int Function to Consume Entire String