typedef void (*p_t)(char* a1, char* a2, int a3);
is a typedef
of a pointer to a function that accepts arguments char* a1, char* a2, int a3
and returns a void
(no return).
Think of a function declaration (without any typedef
involved), for example:
void fn(char* a1, char* a2, int a3);
Now, suppose that you want some pointer p
to point to this function, then an assignment like p = fn
should make sense. But what would the type of that p
be? It would be a pointer to a function, but since functions have different signatures (making the "type" of the function different), you need to also specify the signature of the function that it points to. In your case, you need a pointer to a function that accepts three arguments: 1.) a pointer to a char
, 2.) another pointer to a char
, and 3.) an int
. Also, the function returns a void
. All this needs to be specified in the type of p
. So your p
might be declared (and subsequently assigned) as
void (*p)(char* a1, char* a2, int a3);
p = fn;
The part that may look weird is the *
(declaring p
as a pointer to something), which needs to go in parentheses with the p
identifier. Seeing some construct like (*p)(...)
should be a quick hint to ask yourself if you're looking at a pointer to a function. If you're going to use such a pointer to a function over and over, rather than have to type all that out again and again (and risk inconsistencies should you decide to change the function signature), it is convenient to make a typedef
. In your case, this is
typedef void (*p_t)(char* a1, char* a2, int a3);
See the "Clockwise/Spiral Rule".
In your example, you have
p_t p = &some_function;
This is declaring a variable p
of type p_t
. As mentioned above, this is a pointer to a function that accepts three arguments and returns a void
. This line also initializes p
with the value &some_function
. Apparently some_function
is the identifier of a function that is defined somewhere and accepts these three arguments and returns a void
. It initializes p
to point to this function, so that on the next line calls it:
p("foo", "bar", 42);
I'm surprised this isn't written as
(*p)("foo", "bar", 42);
This dereferences p
, which gives the function some_function
, then calls that function with the arguments "foo"
, "bar"
, and 42
. This is convenient because you could (if you wanted) make p
point to some other function (with the same signature). The associated function can therefore be dynamic.
It is worth mentioning that the &
in p_t p = &some_function;
is not necessary. It doesn't hurt anything, but it's not needed. Another strange thing about pointers to functions is that you can reference and dereference as many times as you want, and they mean the same thing! (See
Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?)