16

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?

9
  • 1
    You can typedef. Commented Jun 1, 2018 at 8:11
  • 2
    A function signature is the function as whole. It is therefore logically an impossible requirement to have "func1(int a, int b) returns a pointer to another function func2(int a, int b). func2 also returns a function pointer with the same signature as func1" Commented Jun 1, 2018 at 8:16
  • 3
    Ignoring the failing logic that makes the question impossible to answer, I suspect you are looking for something like typedef void func_t (int, int); and func_t* func1 (int a, int b); Commented Jun 1, 2018 at 8:22
  • 1
    To tidy-up your legacy code, instead of returning the function, return an enum and then call the function identified by the enum (e.g. use a table of functions). What the code did is no longer supported by modern compilers and modern architectures. Commented Jun 1, 2018 at 9:31
  • 1
    @SimonBagley See also this question in the old C FAQ list. Commented Jun 1, 2018 at 10:04

3 Answers 3

19

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.

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

22 Comments

@Lundin: If functions represent states, a transition can be represented by returning the next state.
@Lundin: There is nothing particularly complicated here.
@Lundin: You are overthinking it. The complexity in a state machine is not how a particular transition is represented, but how to manage the decisions within the state that may branch to (perhaps many) different states as the next state. There is little difference between raising an event or returning a state directly in terms of the number of edges that have to be managed. Either way, you need a validator to determine that the state is making a valid transition. How the transition is coded doesn't really matter much.
@Stargateur: I guess I didn't define directly, but I did assume the OP didn't want to use a cast to invoke the function.
@Lundin You may not like it, and your counterarguments are well taken, but representing states as pointers to the functions that implement them is a popular and (in its way) elegant approach. I suppose assembly language programmers are used to doing it this way. People have been asking how to write "infinitely nested" function pointers forever; that's why the question appears in the old C FAQ list. (I could list some arguments against states-as-enums, too, but this isn't the place for it.)
|
9

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

4 Comments

(*(*((*foo)()))())() somehow reminds me of Brain-Flak :-)
Your function pointer declaration at the start of your answer has a redundant pair of parentheses and could be simplified to char (*(*(*foo)())())();. Also I think the idea of this question is that the function pointer type should be recursive and return a function pointer which returns the same type of function pointer which can be repeatedly called forever without eventually ending up with just a char.
nothing like recursive declarations exists in the C language. Only in the function body.
(*(*((*foo)()))())() looks like lisp :D
1

I think the real problem in C is that you get an infinite declaration as the function returns a function pointer and that function pointer needs to be typed to return a function pointer which needs to be typed to....

The following are a few steps in such an infinite declaration, just to show how the declaration expands and expands:

int f0(int a) {
    return 1;
}
int (*f1(int a))(int) {
    return f0;
}
int (*(*f2(int a))(int))(int) {
    return f1;
}


As a solution for the legacy code, it can return a state number and a table with functions can be used to call the function defined for the state, for example:

#define STATE0 0
#define STATE1 1

int fx1(int a);
int fx2(int a);

int (*ftab[])(int) = {
    fx1,
    fx2
};

void examplefunc(void)
{
    int x = ftab[STATE1](3);  // example of calling function from table
}

Comments

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.