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 thesizeof
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
Importing Modules: _Main_ VS Import as Module
Pandas Group by and Find First Non Null Value for All Columns
Getting Started with the Python Debugger, Pdb
How to Use Groupby to Concatenate Strings in Python Pandas
Python - Using Pandas Structures with Large CSV(Iterate and Chunksize)
When Should I Subclass Enummeta Instead of Enum
Is It Still Necessary to Install Cuda Before Using the Conda Tensorflow-Gpu Package
Subprocess Readline Hangs Waiting for Eof
Python's JSON Module, Converts Int Dictionary Keys to Strings
How to Access Function Variables in Another Function
Pandas Fill Missing Values in Dataframe from Another Dataframe
Hiding a Password in a Python Script (Insecure Obfuscation Only)
How to Read a Function's Signature Including Default Argument Values