How to Pass an Argument to a Function Pointer Parameter

How can I pass arguments to the function pointer in following code?

This kind of call is easier to understand if you typedef your function pointer:

#include<conio.h>
#include<stdio.h>

// addFuncPtr_t is a pointer to a function that:
// - returns int
// - takes two int arguments
typedef int ( *addFuncPtr_t )( int, int );

int add(int x, int y) {
return (x + y);
}
void passptr(addFuncPtr_t fp, int a, int b) {
int result = fp(a, b);
printf("%d", result);
}
int main() {
add(3, 5);

// note that the function is passed separately from
// the arguments - add(3,5) would *call* the function
// instead of passing the address of the function
passptr( add, 3, 5 );
getch();
return 0;
}

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);
}
...
}

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 );

Pass a function or pass a function pointer in C?

Is there an actual difference between all of my 4 snippets? Why all of them behave exactly the same?

All four code snippets are the same.

With regard to how execute is called, this is covered in section 6.3.2.1p4 of the C11 standard:

A function designator is an expression that has function type. Except when it is the
operand of the sizeof operator, the _Alignof operator, or the unary & operator, a
function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.

So calling execute(print) or execute(&print) are the same because of this.

Regarding the parameter to execute, this is covered in section 6.7.6.3p8:

A declaration of a parameter as ‘‘function returning type’’ shall be adjusted to ‘‘pointer to
function returning type’’, as in 6.3.2.1

So this means void execute(void (*f)()) and void execute(void f()) are the same.

Which one of the 4 snippets should I use, and why?

This tends to be a matter of style, but I would personally declare variables and parameters as a pointer-to-function type rather than a function type, and I would pass the function name without the address-of operator.

Should I invoke the passed function received via parameter with f() or with (*f)()

This is also a matter of style. I would go with f() as its easier to read.

Why in the first print of each snippet, the size of the function variable (sizeof(print)) is always 1? What are we actually getting the sizeof in this case? (it obviously not the size of a pointer, which would be 8 bytes in my 64-bit machine. I would get the size of a pointer if I used sizeof(&print))

Using sizeof on a function designator is explicitly disallowed as per section 6.5.3.4p1:

The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member. The _Alignof operator shall not be applied to a function type or an incomplete type.

And doing so invokes undefined behavior.

Why on snippets 1 and 3, in the second print, sizeof(f) gives me 8 (the size of a pointer), even though the parameter is declared as void (f)() (so without a *, I could assume it is not a pointer)

This goes back to 6.7.6.3p8 above, namely that a function parameter of type function is converted to type pointer-to-function, so that's what you're getting the size of.

How to pass an argument to a function pointer parameter?

You can either use a lambda:

repeat(lambda: bar(42))

Or functools.partial:

from functools import partial
repeat(partial(bar, 42))

Or pass the arguments separately:

def repeat(times, f, *args):
for _ in range(times):
f(*args)

This final style is quite common in the standard library and major Python tools. *args denotes a variable number of arguments, so you can use this function as

repeat(4, foo, "test")

or

def inquisition(weapon1, weapon2, weapon3):
print("Our weapons are {}, {} and {}".format(weapon1, weapon2, weapon3))

repeat(10, inquisition, "surprise", "fear", "ruthless efficiency")

Note that I put the number of repetitions up front for convenience. It can't be the last argument if you want to use the *args construct.

(For completeness, you could add keyword arguments as well with **kwargs.)

Callback: function pointer as argument and passing an aditional agrument

You should make D taking two parameters, one for the function pointer, one for the argument to be passed to function pointer. E.g.

void D(void (*ptr2)(string), const string& name){
ptr2(name);
}

then call it like

D(q, "John Doe");

Function pointer as an argument

Definitely.

void f(void (*a)()) {
a();
}

void test() {
printf("hello world\n");
}

int main() {
f(&test);
return 0;
}

Adding missing arguments to function pointer in another function

You need to change loopFunction to take the additional arguments you want to pass through, expand the parameter pack in the function pointer type and pass the arguments when you call the function pointer:

template<typename T, typename ... Args>
void loopFunction(
int iter,
array<T> array,
void (*function)(Args..., int, int),
Args... args
)
{
// loop on iter
for(int i = 0; i < iter; ++i)
{
// Loop on input array size
int arraySize = array.size();
for(int j = 0; j < arraySize; ++j)
{
function(args..., i, j);
}
}
}

Then in the calling function (note this shouldn't be called main) you can't pass the parameters when getting the function pointer and they need to be passed to loopFunction directly:

// Call loopFunction, passing processVec2 as function pointer argument. I need to set the function's argument here too.
loopFunction<vector2>(vec2_iter, vec2_array, &processVec2, a, b, vec2_array);

// Call loopFunction, passing processVec3 as function pointer argument. I need to set the function's argument here too.
loopFunction<vector3>(vec3_iter, vec3_array, &processVec3, a, b, c, d, vec3_array);

It may be simpler to use lambdas instead:

template<typename T, typename Function>
void loopFunction(
int iter,
array<T> array,
Function function
)
{
// loop on iter
for(int i = 0; i < iter; ++i)
{
// Loop on input array size
int arraySize = array.size();
for(int j = 0; j < arraySize; ++j)
{
function(i, j);
}
}
}

// Call loopFunction, passing processVec2 as function pointer argument. I need to set the function's argument here too.
loopFunction<vector2>(vec2_iter, vec2_array, [&](int i, int j){ processVec2(a, b, vec2_array, i, j); });

// Call loopFunction, passing processVec3 as function pointer argument. I need to set the function's argument here too.
loopFunction<vector3>(vec3_iter, vec3_array, [&](int i, int j){ processVec3(a, b, c, d, vec3_array, i, j); });



Related Topics



Leave a reply



Submit