Search code examples
ctypedeftype-definition

How to use this defined type in C?


How can I use this defined type ?

typedef void (*(workers[2]))(char *, char *, int);

What I could understand, that I'll have workers, which is an array of two pointers, each one points to a void, which accepts the mentioned arguments.

Is that correct ?

Trial #1

void worker1(char * x, char * y, int z) {

}

void worker2(char * x, char * y, int z) {

}

and then inside some another void, I did:

workers w;
w[0] = worker1;
w[1] = worker2;

Compiling, I get: error: cannot convert `void (**)(char*, char*, int)' to `void (* (*)[2])(char*, char*, int)'


Solution

  • workers is an alias for the type "2-element array of pointers to functions taking two char * and an int as arguments and returning void".

    Here's an example of what this beast might look like in practice.

    void f0( char *foo, char *bar, int bletch )
    {
      // do something interesting with foo, bar, and bletch
    }
    
    void f1( char *foo, char *bar, int bletch )
    {
      // do something else interesting with foo, bar, and bletch
    }
    
    int main( void )
    {
      workers w = { f0, f1 }; // equivalent to void (*w[2])(char *, char *, int ) = { f0, f1 };
    
      // call f0 through w:
      w[0]( "blah", "blah", 1 );
    
      // call f1 through w:
      w[1]( "ugh", "blah", 2 );
      ...
    }
    

    The workers typedef basically creates a shorter name for a complicated, hard-to-read type. In practice, it would probably be better to create a typedef for just the function type, then create an array of that:

    typedef (*worker)(char *, char *, int );
    worker w[2] = { f0, f1 };
    

    The problem with a declaration like

    workers w = { f0, f1 };
    

    is that it's not immediately obvious that w has an array type, so the initialization looks confusing. It also relies on the person using this type to know that it's an array type of a certain size. We call that a "leaky abstraction", and they lead to confusion and maintenance headaches.

    You still have to know that each w[i] is a function type that takes a certain number and type of arguments, so ideally that should be hidden behind an interface as well (i.e., you pass w[i] to a function that knows how to call it, rather than calling it yourself).