Forward Declaration of Function Type in C
Asked Answered
S

1

6

I want to declare a recursive function type (a function which declares itself) in C.

In a language like Go I can do:

type F func() F

func foo() F {
  return foo
}

If I try to do the equivalent in C:

typedef (*F)(F());

I get the following error from GCC:

main.c:1:14: error: unknown type name ‘F’
    1 | typedef (*F)(F());

Which makes sense because F doesn't exist at the time of its use. A forward declaration could fix this, how do you forward declare a function type in C?

Snarl answered 25/1 at 0:44 Comment(2)
I suspect the best you can do is to declare a function whose parameter is a function (automatically adjusted to be a pointer to a function) whose parameter is a function…, nested any number of levels deep to end in a function whose parameters are not specified (uses () for the argument list), such as typedef int F(int (int (int (int ()))));. In C, the scope of an identifier begins at the end of its declarator, and function declarators include the (…) specifying the parameters. And you cannot redeclare typedef identifiers with a different type, so you cannot complete it later.Targum
Re "typedef (*F)(F());", I think you mean typedef F *F( void ); (function type) or typedef FPTR (*FPTR)( void ); (function pointer type). But this doesn't change the problem.Yovonnda
Y
7

C doesn't support recursive type definitions.

Exception: You can use a pointer to a struct type you haven't declared, so a struct type can include a pointer to a struct of the struct type being declared.

Also, you can apparently use a struct type you haven't yet declared as the return value of a function. So this is close to what you want:

// This effectively gives us
// typedef struct { F *f } F( void );

typedef struct S S;

typedef S F( void );

struct S {
   F *f;
};

S foo() {
   return (S){ foo };
}

int main( void ) {
   F *f = foo;
   printf( "%p\n", (void*)f );

   f = f().f;
   printf( "%p\n", (void*)f );
}
Yovonnda answered 25/1 at 1:53 Comment(5)
But if you then want ways to create more values of type F by compounding other operations, that will be difficult or limited.Hardiman
@aschepler, Ways to create more functions of type F? I don't follow.Yovonnda
As for difficult or limited? It's just a question of wrapping return values (or parameters) using (S){ x }, and unwrapping returned values (or arguments) using x.f. Not pretty, but hardly difficult. If you want pretty, just use a void* and live with the lack of type checking.Yovonnda
For example, can you write F * curry(F*); such that for any f, curry(f)() is functionally the same as f? Or F * seq(F*, F*); such that seq(f,g)() has the same side effects as (f(), g())?Hardiman
@aschepler, Ah, you were commenting to the OP, not on my answer. C doesn't have closures, but there are libraries that introduce them. Reference.Yovonnda

© 2022 - 2024 — McMap. All rights reserved.