The code I am using has this statement:
typedef void ( udp_data_notify )(OS_FIFO * pfifo, WORD port);
This looks like a declaration of a function pointer for udp_data_notify, however there is no *. Can it still be a function pointer without an asterisk?
Here is a statement that uses udp_data_notify:
void RegisterUDPFifoWithNotify( WORD dp, OS_FIFO *pnewfifo , udp_data_notify * nudp)
Any help as to what is happening would be appreciated!
A typedef such as:
typedef void name(int);
(the parenthesis around name are redundant) will define name as the type of a function, not a function pointer. That would be:
typedef void (*pname)(int);
You are probably wondering what they are good for. Well, function types are not very useful, other than for declaring pointers:
name *pointer_to_function;
And that can be made arguably more readable with the other typedef:
pname pointer_to_function;
That's because you cannot define a variable of type function. If you try, you will simply write the prototype of a function, but in a quite obfuscated syntax:
name foo; //declaration (prototype), not variable
void foo(int x) //definition
{
}
But note that you cannot use the typedef to define the function:
name foo {} //syntax error!
As already said, the typedef declares an alias for function type. When you want to use it to declare a function pointer, an asterisk is required (udp_data_notify* x). A declaration without the asterisk (udp_data_notify x) would be a function declaration, except in one special case. When used in a parameter a function type is automatically turned into the corresponding function pointer type:
typedef void F(void);
void foo(F a, F* b) // special case; a and b are both function pointers
{
F c; // function declaration
F* d; // function pointer
}
The typedef you show declares udp_data_notify to be an alias for a function type. Then the parameter declaration udp_data_notify *nudp declares nudp to be a pointer to a function of that type. There is no function call here.
Regarding the function-call operator (postfix ()), the expression that designates the called function must be a pointer to a function. When you call a function normally, without a pointer, such as sqrt(2), the function is automatically converted to a pointer for you. So sqrt(2) is actually (&sqrt)(2). When you call a function with a pointer, the call is in the right form already.
Related
I'm confused about the meaning of void *function().
Is it a pointer to function or a function returning void*? I've always used it on data structures as a recursive function returning a pointer, but when i saw a code in multithreading (pthread) there is a same function declaration. Now I'm confused what's the difference between them.
The function has the return type void *.
void *function();
So I always prefer in such cases to separate the symbol * from the function name like
void * function();
And as Jarod42 pointed to in a comment you can rewrite the function declaration in C++ using the trailing return type like
auto function() -> void *;
If you want to declare a pointer to function then you should write
void ( *function )();
where the return type is void Or
void * ( *function )();
where the return type void *.
Or a pointer to function that returns pointer to function
void * ( *( *function )() )();
Whenever I'm unsure about C syntax issues, I like to use the cdecl utility (online version) to interpret for me. It translates between C syntax and English.
For example, I input your example of void *foo() and it returned
declare foo as function returning pointer to void
To see what the other syntax would look like, I input declare foo as pointer to function returning void and it returned
void (*foo)()
This gets particularly useful when you have multiple levels of typecasts, stars, or brackets in a single expression.
It is a function returning a pointer to void.
Think of your declaration this way:
void *(function());
This would be a function returning void (or nothing):
void (*function2)();
Think of the above declaration this way:
void ((*function2)());
A much easier way to write these is to use typedefs:
typedef void *function_returning_void_pointer();
typedef void function_returning_nothing();
function_returning_void_pointer function;
function_returning_nothing *function2;
This generally eliminates the confusion around function pointers and is much easier to read.
Declarations in C/C++ are read from the identifier outwards following operator precedence.
A quick look at the C/C++ operator precedence table in wikipedia reveals that the function call operator () has a higher precedence than the indirection operator *. So, your function declarations reads like this:
Start at the identifier: function is
function() a function that takes no arguments
void* function() and returns a void*.
This general principle also holds with array declarations ([] also has higher precedence than *) and combinations of the two. So
int *(*arr[42])();
is read as
arr is
arr[42] an array of 42 elements which are
*arr[42] pointers to
(*arr[42])() functions that take no arguments and
int *(*arr[42])() return an int*.
It takes a bit to get used to this, but once you've understood the principle, it's easy to read those declarations unambiguously.
I just started learning C, and I came across this in one of the example given, I know this is a function prototype, but the concept I am yet to wrap my head around is the fact that does
void function(char *);
mean when I finally declare the function, it is going take an argument char pointer argument like so
void function(char *arg){}
?
Just to answer the question you gave:
What does “void fatal(char *);” mean?
This is the prototype/declaration of the function fatal.fatal is a function, which takes a pointer to char as one and only argument.
void is the return type of the function, which in this case mean that the function does not return a value to its caller or if it does, the value returned is interpreted as invalid by the caller.
The prototype/declaration of the function fatal() is important for the compiler. In this way, primarily the compiler will get "known", how the function is later used in the following program but secondary also checks if there are any inconsistencies between the definition, declaration and the use of the function.
In C, You may omit a specific identifier for the pointer to char in the declaration of the function, but not in the definition. This a circumstance where C is different as C++; In C++ it is permissible to omit the identifier also in the definition. You can look at the respective phrases in the standards in this answer.
So in the definition of fatal in C you have to provide an identifier for the char pointer:
// Definition of function fatal().
void fatal(char *a)
{
printf("The string of (a) is: %s\n",a);
}
but you can omit this one in the declaration:
void fatal(char *);
Note: The identifier between the provided arguments, when calling the function and the parameters specified in the declaration of the function may vary, like:
// Declaration (Protoype) of function fatal().
void fatal(char* a); // parameter a (pointer to char);
int main()
{
char b[] = "Hello"; // Declaration and Initialization of array b.
printf("Let´s use the function fatal to print what the string in b is
contained of!\n");
fatal(b); // when given as argument to a function, b
// is a pointer to the first element of the char
// array of b.
}
// Definition of function fatal().
void fatal(char* a)
{
printf("The string of (a) is: %s\n",a);
}
See more about the difference between parameters and arguments here: What's the difference between an argument and a parameter?
In the more far view, there is also an important difference between "pass by value" and "pass by reference". A pointer argument/parameter is always a pass by reference. What these two especially are and how they distinct is best explained here: What's the difference between passing by reference vs. passing by value?
In this context and the context of scope visibility, it is also important to know if you have f.e. an identifier x which refers to an object in the function fatal, the same identifier of x can be used in the caller, and vice versa, to refer to a total different object in each scope. - Means, you can have the same identifier (name) for different objects in different scopes but each identifier can only used once in its scope.
Here void function(char *); is a function prototype which is simply the declaration of a function that specifies function's name, parameters and return type. It doesn't contain function body.
It gives information to the compiler that the function may later be used in the program.
It is not needed if the user-defined function is defined before the main() function.
does
[...] mean when I finally declare the function, it is going take an argument char pointer argument [...]
?
Yes, it does.
The important thing with the declaration of the function are the parameters' types. The parameters' names are not needed within the declaration
void function(char *);
but only within the function's definition
void function(char *arg)
{
}
.
It just informs the compiler what type parameters functions takes and what is the return type of it.
int main()
{
double x = foo(1,2);
}
void foo(double x)
{
printf("%f", x);
}
in this compiler does not know what parameters of the function foo are and how to pass them properly. Return type is also unknown. The compiler will assume they are int - which is not the truth in this case
https://godbolt.org/z/J8juc4
I'm having problems understanding the syntax of a pointer to a function using typedef. I've read a lot of answers but still couldn't understand something.
I'll try to explain how I see things so you could understand my thinking.
So we use typedef to give aliases to existing types for example :
typedef int number;
Will make it so we could use a number same as an integer (similar to preprocessor directives - I know there're some differences like when making a typedef of a pointer).
Another example :
typedef struct
{
int num;
} MyStruct;
Will give the unnamed structure an alias named MyStruct.
So Here's the syntax of a pointer to function typedef:
typedef int (*pFunc)(int, int);
Maybe I'm having hard time to understand this since typedef is like it's name giving aliases to TYPES and a function is not exactly type but anyway, from my understanding this is more of a pointer to some sort of a function signature, so the first int is the returned type, the second parenthesis are to indicate what types are the arguments being passed to the function.
Now what I don't quite understand is this part :
(*pFunc)
What I think it is, is that we create a new type (using typedef)
named pFunc that is a pointer and that's the role of the *. Now we
could create variables of this type that will point to ANY function
with the signature we described. Am I correct ?
Ok, say I'm correct, usually pointers to some memory are declared as follow :
int *p;
double *p;
.
.
.
So wouldn't it make more sense to do it as follow :
(pFunc*)
Because to me it looks like if the asterisk is before the name it looks like pFunc is a variable name of type pointer of some type and not an actual type pointer.
Can we do that ^ ? If so, is it commonly used to put the asterisk
after and not before ? If it's more common to put it before then why
is that ? Because like I said when we define a pointer type we always
put the asterisk after the name itself like the examples above so why
is that exactly ?
Another question regarding to this, I don't quite understand what are
the job of the parenthesis around *pFunc.
I think that they're used to indicate that pFunc type pointer of something and if we wouldn't do put parenthesis then the return type
of the signature will be of type int* instead of just int, am I
correct here ?
Ok, another thing that bothers me about it as the order of the syntax.
So far, in all typedef definitions we had the type on the left and the alias(es) on the right.
typedef int number;
typedef struct
{
int num;
} MyStruct;
We see that the int and the struct are the types which are being on the left and the alias we gave them are on the right.
Now, in pointers to function typedef it doesn't follow this convention.
We have the type returned of the function on the right then the typename in parenthesis then the type of the arguments in parenthesis, this order makes me confused after looking on how the other typedef are working on the same order.
Wouldn't it make more sens to do something like this ? :
typedef int (int,int) Func; So we have a typedef first, the type we want to give alias(es) to, which in this case is a function
signature which takes 2 ints and return an int, and then on the right
we have the alias name. Won't it make more sense ? this follows the
other typedef order, I just don't get the function pointer order that
much ..
Another question of mine : When we make a pointer to a function, what
does it actually mean ? I understand we can call this function using
our alias but pointers like variables are stored in a memory address
? What is there to store for a function ?
Lastly, I've read that the keyword extern has something to do with
pointers to function but couldn't understand what this keyword does,
could someone explain to me what it does ?
The typedef uses the same syntax for declaring types as would normally be used for declaring values.
For instance, if we declare an int called myInt, we do:
int myInt;
If we want to declare a type called myIntType to be an int, we simply add typedef:
typedef int myIntType;
We can declare a function myFunc, as follows:
int myFunc(int a, int b);
Which tells the compiler that there is an actual function with that name and signature that we can call.
We can also declare a function type myFuncType by doing:
typedef int myFuncType(int a, int b);
And we could do:
myFuncType myFunc;
Which is equivalent to the previous declaration of myFunc (although this form would rarely be used).
A function is not a conventional value; it represents a block of code with an entry point address. Function declarations like those above are implicitly extern; they tell the compiler that the named thing exists somewhere else. However, you can take the address of a function, which is called a function pointer. A function pointer can point to any function with the correct signature. A pointer is declared by prefixing the name of the type/value with a *, so, we might try:
int *myFuncPtr(int a, int b);
But this would be incorrect because the * binds more tightly with the int, so we have declared that myFuncPtr is a function that returns a pointer to an int. We must put parens around the pointer and name to change the binding order:
int (*myFuncPtr)(int a, int b);
And to declare a type, we simply add typedef to the front:
typedef int (*myFuncPtrType)(int a, int b);
In the declaration of myInt above, the compiler allocated some memory for the variable. However, if we were writing some code in a different compilation unit, and wanted to reference myInt, we would need to declare it as extern (in the referencing compilation unit) so that we reference the same memory. Without the extern, the compiler would allocate a second myInt, which would result in a linker error (actually that's not quite true because C allows tentative definitions, which you shouldn't use).
As noted above, functions are not normal values, and are always implicitly extern. However, function pointers are normal values, and need the extern if you are trying to reference a global function pointer from a separate compilation unit.
Normally, you would put externs for your global variables (and functions) into a header file. You would then include the header into the compilation units that contain the definitions of those variables and functions so that the compiler can make sure the types match.
The syntax for a variable definition or declaration is the type followed by one or more variables possibly with modifiers. Some simple examples would be:
int a, b; // two int variables a and b
int *a, b; // pointer to an int variable a and an int variable b
int a, *b, **c; // int variable a, pointer to an int variable b, and pointer to a pointer to an int variable c
Notice that in all of these the asterisk modifies the variable to the right of the asterisk, changing it from an int into a pointer to an int or a pointer to a pointer to an int. The variables defined might be used like:
int a, *b, **c, d;
a = 5; // set a == 5
b = &a; // set b == address of a
c = &b; // set c == address of b which in this case has the address of int variable a
d = **c; // put value of a into d using pointer to point to an int variable a
d = *b; // put value of a into d using pointer to an int variable a
d = a; // put value of a into d using the variable a directly
The extern statement
The extern statement is used to indicate that the definition of a variable is located in some other file and that the variable has global visibility. So you can declare a variable using the extern keyword to be explicit about a variable so that the C compiler will have the information it needs to do a good level of checking when compiling. The extern indicates that the variable is actually defined with its memory allocation somewhere other than the file where the source using the variable is located.
Using typedef
The typedef is a very nice feature of modern C because it allows you to create an alias that amounts to a kind of halfway new type. To have the full capability of creating a new type really requires the class type features of C++ which allows the definition of operators for the new type as well. However typedef does provide a good way of allowing a programmer to create an alias for a type.
Most uses of typedef are to provide a way to make it shorter and cleaner to write a variable definition. It is used a lot with struct definitions for that reason. So you might have a struct definition like the following:
typdef struct {
int iA;
int iB;
} MyStruct, *PMyStruct;
This will create two new aliases for the struct, one for the struct itself and one for a pointer to the struct and these might be used like:
MyStruct exampleStruct;
PMyStruct pExampleStrut;
pExampleStruct = &exampleStruct;
This example has the basic structure of typedef keyword, definition of the new type in terms of existing types, and name of the new type.
Old style C before typedef
Years ago in the older C compiler days before typedef was added to the C standard, people would often use the C Preprocessor to define macros to create an alias for a complex type. typedef is a much cleaner way of doing it!
Before typedef was added to the C standard, you would specify a tag for the struct and the result would be code that looked like this:
struct myTagStruct { // create a struct declaration with the tag of myTagStruct
int a;
int b;
};
struct myTagStruct myStruct; // create a variable myStruct of the struct
At which pointer people would usually add a C Preprocessor define to make it easier to write as in:
#define MYTAGSTRUCT struct myTagStruct
and then use it something like:
MYTAGSTRUCT myStruct;
However there is one major difference between using the preferred typedef syntax rather than the Preprocessor define approach. The Preprocessor works with the text of the C source code file to generate a modified version of the C source which is then compiled by the C compiler. The typedef keyword is part of the C source compiled by the C compiler so the C compiler knows about the type alias defined.
To show the difference, see the following source code.
#define PMYSTRUCT MyStruct *
typedef struct {
int a1;
int b1;
} MyStruct, *PMyStruct;
MyStruct sA, sB; //
PMyStruct psA, psB; // compiler sees this as MyStruct *psA, *psB;
PMYSTRUCT psxA, psxB; // Preprocessor generates MyStruct * psxA, psxB;
psA = &sA;
psB = &sB;
psxA = &sA;
psxB = &sB; // compiler error - psxB is not a pointer variable
Using typedef with function pointers
The syntax of typedef for function pointers is a bit unusual. It looks somewhat like a function declaration but does have a slight twist with an additional pointer syntax.
typedef int (*pFunc)(int a1, int b1);
This says the following:
create a typedef for a variable type pFunc
a variable defined as a pFunc type is a pointer
what the variable points to is a function with two int arguments that returns an int
The parenthesizes are important because they force the compiler to interpret the source text in a way different from the default rules. The C compiler has rules that it uses to parse the source text and you can change the way that the C compiler interprets the source text by using parenthesizes. The rules have to do with the parsing and how the C compiler locates the variable name and then determines the type of the variable by using rules about left and right associativity.
a = 5 * b + 1; // 5 times b then add 1
a = 5 * (b + 1); // 5 times the sum of b and 1
int *pFunc(int a1, int b1); // function prototype for function pFunc which returns a pointer to an int
int **pFunct(int a1, int b1); // function prototype for function pFunc which returns a pointer to a pointer to an int
int (*pfunc)(int a1, int b1); // function pointer variable for pointer to a function which returns an int
int *(*pFunc)(int a1, int b1); // function pointer variable for pointer to a function which returns a pointer to an int
A function prototype is not a function pointer variable. The syntax of a typedef is similar to the syntax for a variable definition that is not using a typedef.
typedef int * pInt; // create typedef for pointer to an int
int *a; // create a variable that is a pointer to an int
pInt b; // create a variable that is a pointer to an int
typedef int (*pIntFunc)(int a1, int b1); // create typedef for pointer to a function
typedef int *pFuncWhat(int a1, int b1); // create a typedef for a function that returns a pointer to an int. seems to be legal but useful? doubt it.
int (*pFuncA)(int a1, int b1); // create a variable pFuncA that is a pointer to a function
int *FuncDecl(int a1, int b1); // declare a function that returns a pointer to an int
pIntFunc pFuncB; // create a variable pFuncB that is a pointer to a function
So what does it mean to have a pointer to a function? A function entry point has an address because a function is machine code that is located at a particular memory area. The address of the function is where the execution of the functions machine code is supposed to start.
When the C source code is compiled, a function call is translated into a series of machine instructions which jump to the address of the function. The actual machine instructions are not really a jump but are instead a call instruction which saves the return address before it makes the jump so that when the called function completes it can do a return back to where it was called from.
A function pointer variable is used like a function statement. The difference between the two is similar to the difference between an array variable and a pointer variable. An array variable is treated like a constant pointer to a variable by most C compilers. A function name is treated like a constant pointer to a function by most C compilers.
Using a function pointer
What a function pointer does give you though is flexibility though it is flexibility that as with any great power can also lead to great ruin.
One use of function pointer variables is to pass a function address as an argument to another function. For instance the C Standard library has a couple of sort functions that require an argument of a collation function for comparing two elements being sorted. Another example would be a threading library that when you create a thread, you specify the address of the function to be executed as a thread.
Since a function pointer is a variable then if you have a function pointer that needs global visibility when you declare the variable for files other than the source file where it is actually defined and its memory allocated you would use the extern keyword as part of the function pointer variable declaration. However if it is a variable that is allocated on the stack within a function or if it is used within a struct to create a member of the struct then you would not use the extern modifier on the variable.
file1.c
// define a function that we are going to make available
// through a function pointer. a function will have global
// visibility unless we use the static keyword to reduce the
// visibility to this source file.
static int myfunc(int a, float b)
{
return (a + (int) (b * 100.0));
}
// define a function pointer that contains the address of the
// function above that we are exporting from this file.
// this function pointer variable automatically has global visibility
// due to where the statement is located in the source file.
int(*pmyfunc)(int, float) = myfunc;
file1.h
// declare the function pointer, which has global visibility
// due to where it was defined in the source file. we declare
// the function pointer in an extern in order to make the
// function prototype with argument types available to the compiler
// when using this variable in other source files.
extern int(*pmyfunc)(int, float);
file 2.c
#include "file1.h"
int iifunc (int a, int b)
{
return (a + b/10 + 5);
}
// define a function that has as an argument a function pointer
// variable. this allows the caller to inject into the processing
// of this function a function to be used in the function.
int jjfunc (int a, int (*pf)(int, float))
{
return ((a / 10) + pf(a, 2000.0));
}
int kkfunc (int a, char *pName)
{
// an example of a local definition of a function pointer.
// we could have used pmyfunc directly.
int(*plocalfunc)(int, float) = pmyfunc;
// following two statements show difference between calling a
// function with a function pointer argument and calling a
// function with a function call in the argument list.
int k = jjfunc(a, plocalfunc);
int l = iifunc(a, pmyfunc(a, 3000.0));
printf ("%s - %d\n", pName, k);
return k;
}
Another case is to provide some kind of interface that hides implementation details. Let's say that you have a print function that you want to use for several different output sinks or places where the output to go, say a file, a printer, and a terminal window. This is similar in nature to how virtual functions are implemented by C++ compilers or how COM objects are implemented through a COM interface. So you could do something like the following which is a very simple example missing details:
typedef struct {
int (*pOpenSink) (void);
int (*pPrintLine) (char *aszLine);
int (*pCloseSink) (void);
} DeviceOpsStruct;
DeviceOpsStruct DeviceOps [] = {
{PrinterOpen, PrinterLine, PrinterClose},
{FileOpen, FileLine, FileClose},
{TermOpen, TermLine, TermClose}
};
int OpenDevice (int iDev)
{
return DeviceOps[iDev].pOpenSink();
}
int LineDevice (int iDev, char *aszLine)
{
return DeviceOps[iDev].pPrintLine (aszLine);
}
int CloseDevice (int iDev)
{
return DeviceOps[iDev].pCloseSink();
}
Just to make clear the explanation given by others, in C/C++, the parenthesis are right associative, therefore the following declaration:
typedef int *pFunc(int, int);
is equivalent to:
typedef int *(pFunc(int, int));
which would be the declaration prototype of a function returning a pointer to an integer and not the declaration of a pointer to a function returning an integer.
This is why you need to write the parenthesis around (*pFunc) to break the right association and tell the compiler that pFunc is a pointer to a function and not simply a function.
typedef int (xxx)(int yyy); seems to define a function pointer named xxx which points to a function with a integer parameter yyy.
But I can't understand that syntax...Could any one give a good explanation?
I find typedef int xxx(int yyy); still works. Any difference between them?
This defines a function type, not a function pointer type.
The pattern with typedef is that it modifies any declaration such that instead of declaring an object, it declares an alias to the type the object would have.
This is perfectly valid:
typedef int (xxx)(int yyy); // Note, yyy is just an unused identifier.
// The parens around xxx are also optional and unused.
xxx func; // Declare a function
int func( int arg ) { // Define the function
return arg;
}
The C and C++ languages specifically, and mercifully, disallow use of a typedef name as the entire type in a function definition.
Yes, typedef int (xxx)(int yyy); is the same as typedef int xxx(int yyy); which defines a function type. You can find an example from page 156 C 11 standard draft N1570 . Quote from that page,
All three of the following declarations of the signal function specify exactly the same type, the first without making use of any typedef names.
typedef void fv(int), (*pfv)(int);
void (*signal(int, void (*)(int)))(int);
fv *signal(int, fv *);
pfv signal(int, pfv);
If you have some declarator x in declaration T x, then T x(t1 p1, t2 p2) means function with params p1, p2, returning the same type as the declarator x was having before.
Parenthesis around the declarator means apply modifiers inside the parenthesis first.
In your case there are no modifiers inside the parenthesis. This means that there is no need in them.
Function prototype means There is a function somewhere that has this signature and its name is Blah.
Typedef with the prototype of the function means Lets give a name blah to a function signature. This does not imply that any function with this signature is existing. This name can be used as a type. For example:
typedef int xxx(int yyy);
xxx *func_ptr; // Declaration of a variable that is a pointer to a function.
xxx *func2(int p1); // Function that returns a pointer to a function.
I'm pretty new to C, and I'm having a really hard time reading this line of code and understanding it:
typedef void (*getnxtbyte_t)(void *stream);
From looking around, I now know that it is for a pointer pointing to a function. But could anyone help me clarify this even further? What is the name of this new type? What function is it pointing to? Is the parameter of the function (void* stream)?
Thanks in advance!
It is a tricky syntax to get used to.
What is the name of this new type?
The type is getnxtbyte_t. (You can read that trailing _t as "type". It's a popular convention.)
A variable of type getnxtbyte_t can hold the address of a function that takes one void * parameter and has return type void.
What function is it pointing to?
Wrong question.
That code merely defines the type. No variables are created so there's no "it" to point to anything.
If you know of a function with the correct signature, such as:
void some_func(void*) {}
You may now create a pointer to it using that typedef:
getnxtbyte_t my_function_pointer = some_func;
This typedef creates a type called getnxtbyte_t. That type is for a pointer to a function that returns void (i.e. nothing), as shown in the second word. That function takes a single parameter, which is a void *, shown by stream.
So if you had a function with a declaration like this:
void some_function(void *any_name);
Then you could use a typedef like the one in your post:
void *some_param = NULL;
typedef void (*getnxtbyte_t)(void *stream); // declare typedef
getnxtbyte_t func = some_function; // assign
func(some_param); // call
The function pointer type name is getnxtbyte_t. It's not pointing to anything now -- this is a type of pointer, not an actual pointer. It's just like saying
typedef struct foo {int x;} Foo;
you define a type Foo, but no actual instance of that type. And finally, yes, the function takes a single void* argument, and returns void.
I am also new to C, so if there are any errors please correct me.
A pointer that points to a function is formatted like so:
datatype (*POINTER_NAME)(PARAMETERS);
So that's the data type the pointed function returns, the name of the pointer and the parameters the pointed function takes.
Here's how a function pointer looks compared to a normal function declaration:
// normal function declaration
void getnxtbyte_t(void *stream);
// function pointer
void (*getnxtbyte_t)(void *stream);
typedef allows us to create our own type.
// will create a type called getnxtbyte_t
typedef void (*getnxtbyte_t)(void *stream);
At this point we have only declared a type; we are not pointing to anything. So let's create a pointer named func_ptr and point it to a function.
// func_ptr is a pointer of type getnxtbyte_t
getnxtbyte_t func_ptr = another_function;
// calling func_ptr is now the same as calling another_function
func_ptr(an_argument);
// had we not used typedef, we would type:
void (*getnxtbyte_t)(void *stream) = another_func;
getnxtbyte_t(an_argument);