1

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.

2
  • This is no different from "how to retrieve an int from a function argument". Solve that problem first, and you'll understand this one, too. Commented Nov 17, 2016 at 19:40
  • Your function get_a() does precisely nothing, because all it does is assign to a local variable and then return nothing. A good compiler might even optimize it out entirely. Commented Nov 17, 2016 at 20:33

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

8 Comments

Solution to 1st approach should be int (*get_a())(int) {return &a;}. Messy.
Curious: Does ISO C allow uintmax_t (or uintptr_t) p = (cast_to_type) function_ptr'? even if the destination type is not wide enough for all of function_ptr?
@chux Good question, I have no idea.
@chux Only a pointer to void may be converted to uintptr_t, and vice-versa.
@2501 Thanks for pointing that out. Yet the conversion spec for void* to/from uintptr_t is to maintain equality. (round trip). My comment was wondering if a pointer to any function can be converted (w/o UB) to uintptr_t - without regard to its round-trip equivalency. Perhaps I'll research that more later.
|
2

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.

5 Comments

Thank for a fast reply with a working example, just what i needed:). Been trying several combinations with extra * and &, but apparently no this one.
@PuzzlingProgrammer Glad I could help. Feel free to accept this answer if you found it useful.
That should be printf("... %p ...", (void *)whatever) in both cases, or the behavior is undefined. (This isn't just because we're dealing with pointers-to-functions; printf is variadic, so there is no automatic conversion of pointers; an argument for %p must be cast to void * unless its type already is [const] void * or (in C11 only) [const] char *.)
@zwol Good catch. Edited.
Casting a function pointer to void is ub in a strict implementation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.