Function Pointer as Parameter

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 ints 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



Leave a reply



Submit