Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare a function pointer that returns a function pointer

How do you declare a function pointer that points to a function that has the same parameters and also returns a pointer to a function with the same parameters.

i.e. funcPtr points to func1(int a, int b), and func1 returns a pointer to another function func2(int a, int b). func2 also returns a function pointer with the same signature as func1.

TYPE funcPtr = func1;
funcPtr = funcPtr(0, 1);

How does one declare funcPtr? What should TYPE be?

like image 303
Simon Bagley Avatar asked Jun 01 '18 08:06

Simon Bagley


People also ask

How can a function return a pointer to a function?

Return Function Pointer From Function: To return a function pointer from a function, the return type of function should be a pointer to another function. But the compiler doesn't accept such a return type for a function, so we need to define a type that represents that particular function pointer.

Can we declare a function that can return a pointer to a function of the same type?

You cannot return a function in C - you return a pointer to a function. If you mean to define a function which returns a pointer to a function which again returns a pointer to a function and so on, then you can use typedef to implement it.

How do you declare a function pointer in C++?

We declare the function pointer, i.e., void (*ptr)(char*). The statement ptr=printname means that we are assigning the address of printname() function to ptr. Now, we can call the printname() function by using the statement ptr(s).


2 Answers

Unresolvable self-reference

This is not possible directly. If you try to define a function pointer type where the function's return type is its own type, you will run into an unresolved self-reference, and that would require infinite recursion to resolve.

typedef funcType (*funcType)(void);

Return a struct

You can instead declare that the function return a structure, and the structure can contain a pointer to such a function.

struct func {
    struct func (*func) (void);
};

struct func foo (void);
struct func bar (void);

struct func foo (void) { return (struct func){ bar }; }
struct func bar (void) { return (struct func){ foo }; }

...
    struct func funcPtr = { foo };
    funcPtr = funcPtr.func();

Return a different function pointer type

If you prefer to stick to strictly pointers, you will need to resort to defining functions that return a different function pointer type. Thus, the result of the call would have to be cast back to the proper pointer type before being invoked.

typedef void (*funcPtrType)(void);
typedef funcPtrType funcType(void);

funcType foo;
funcType bar;

funcPtrType foo (void) { return (funcPtrType)bar; }
funcPtrType bar (void) { return (funcPtrType)foo; }

...
    funcType *p = foo;
    p = (funcType *)p();

Return an index

You could instead define your functions to return an index to a table that represents the function that should be invoked.

enum funcEnum { fooEnum, barEnum };
typedef enum funcEnum (*funcType)(void);

enum funcEnum foo (void) { return barEnum; }
enum funcEnum bar (void) { return fooEnum; }

funcType funcTable[] = { [fooEnum] = foo, [barEnum] = bar };

...
    funcType p = funcTable[fooEnum];
    p = funcTable[p()];

This was raised in comments and in Paul's answer, but presented here for completeness.

like image 53
jxh Avatar answered Sep 20 '22 12:09

jxh


This only an example without typedefs. You can try to change the parameters of the functions but the syntax is horrible and usually useless.

char (*(*((*foo)()))())()

foo is pointer to function returning pointer to function returning pointer to function returning char

Or you can use typedefs

for example

typedef int (*foo2)(int, int);

typedef foo2 (*foo1)(int, int);
typedef foo1 (*foo)(int, int);

or more general

typedef int (*foo`n`)(int, int);
typedef foo`n' (*foo'n-1`)(int, int);

...

typedef foo2 (*foo1)(int, int);
typedef foo1 (*foo)(int, int);
like image 20
0___________ Avatar answered Sep 18 '22 12:09

0___________