TrivialCase
TrivialCase

Reputation: 1099

Forward declaration of a function typedef in C

I have a nagging suspicion that this has been asked before, but I'm not finding it...

Suppose I have a typedef for function A that takes a pointer to a function with typedef B, which in turn takes a function of typedef A. If one of these was a struct, I know how I would handle the forward declaration, but for functions I don't know the syntax. Is there one?

I want to be able to do:

typedef void (*function_A_t)(function_B_t f_B);
typedef void (*function_B_t)(function_A_t f_A);

Any hints? Even better, a reference? Incidentally this actually just happened for me, but I was able to fix it another way, although this would actually smoother (better decoupling, less chance of next guy messing it up) if it's possible.

Upvotes: 4

Views: 80

Answers (1)

dbush
dbush

Reputation: 223739

You can do this by taking advantage of the fact that C specifies that a function declaration with no arguments means it takes an indeterminate number of arguments.

So you could do it as follows:

typedef void (*function_A_t)(void (*)());
typedef void (*function_B_t)(function_A_t f_A);

Which allows the following to compile:

void A(function_B_t b)
{
    b(A);
}

void B(function_A_t a)
{
    a(B);
}

int main()
{
    function_A_t a = A;
    function_B_t b = B;
    a(B);
    b(A);
    return 0;
}

Section 6.7.6.3p15 of the C standard states the following regarding the compatibility of function types:

For two function types to be compatible, both shall specify compatible return types. Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions. If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list, both shall agree in the number of parameters, and the type of each prototype parameter shall be compatible with the type that results from the application of the default argument promotions to the type of the corresponding identifier. (In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the adjusted type and each parameter declared with qualified type is taken as having the unqualified version of its declared type.)

The part in bold above specifies that void (*)() is compatible with void (*)(function_B_t)

Upvotes: 6

Related Questions