Puzzling Programmer
Puzzling Programmer

Reputation: 13

How to retrieve a function from a function argument in C?

I'm stuck in getting a function pointer back from a function parameter. Here's an example of what I'm trying to do.

int a(int I)
{
    return I*I;
}

void get_a(int(*R)(int))
{
    R = &a;
}

int main()
{
    int(*function)(int) = NULL;

    printf("function a=%p\n", a);

    get_a(function);
    printf("function a=%p\n", &function); // Is never the right address.

    return 0;
}

Searching the net did not help, I could only find examples of pass a function as parameter, so I gave up and tried solving this problem by myself.

Upvotes: 1

Views: 169

Answers (2)

dbush
dbush

Reputation: 223689

You have two issue here.

First, your function is modifying a local variable, so the result will never be reflected in the caller. You need to pass the address of your function pointer variable, then have get_a accept a pointer-to-function-pointer. By passing the variable's address, you can dereference it and modify it.

The second issue is that your second printf is printing the address of function instead of its value. Pass in the value.

void get_a(int(**R)(int))
{
    *R = &a;
}

int main()
{
    int(*function)(int) = NULL;

    printf("function a=%p\n", (void *)a);

    get_a(&function);
    printf("function a=%p\n", (void *)function);

    return 0;
}

Result:

function a=0x400498
function a=0x400498

Also note the cast to void *. Passing a pointer to printf to be printed via %p is one of the rare cases when casting to a void * is required, otherwise you could run into undefined behavior.

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

First problem is that you print a pointer to function pointer, not its value; it will never give you the right address.

With this issue out of the way, the remaining problem is that R is a function pointer passed by value. Any changes to it inside get_a are local to the function, and do not reflect in the value of function inside main.

You have two solutions to this problem:

  • make get_a return function pointer, and assign function = get_a() in the main, or
  • Pass a pointer to function pointer into get_a, and assign with dereference, i.e. use the same technique that you use for non-function pointers.

Here is how you can implement the second approach:

void get_a(int(**R)(int)) {
    *R = a;
}
...
get_a(&function);

Demo.

Note: ISO C forbids conversion of function pointers to void*, which is what is required to print with %p. I assume that you are doing it for debugging purposes, though.

Upvotes: 3

Related Questions