Generally, we use typedef to get alternate names for datatypes.
For example --
typedef long int li; // li can be used now in place of long int
But, what does the below typedef do?
typedef int (*pf) (int, int);
typedef int (*pf) (int, int);
This means that variables declared with the pf type are pointers to a function which takes two int parameters and returns an int.
In other words, you can do something like this:
#include <stdio.h>
typedef int (*pf)(int,int);
int addUp (int a, int b) { return a + b; }
int main(void) {
pf xyzzy = addUp;
printf ("%d\n", xyzzy (19, 23));
return 0;
}
typedef long int li;
assigns alternate name li to type long int.
In exactly the same way
typedef int (*pf) (int, int);
assigns alternate name pf to type int (*) (int, int). That all there is to it.
As you probably noticed, typedef declarations follow the same syntax as, say, variable declarations. The only difference is that the new variable name is replaced by the new type name. So, in accordance with C declaration syntax, the declared name might appear "in the middle" of the declarator, when array or function types are involved.
For another example
typedef int A[10];
declares A as alternate name for type int [10]. In this example the new name also appears "in the middle" of the declaration.
It's a function pointer prototype. You can then declare a function as an argument something like this:
void RegisterCallback(pf your_callback_func);
Then you can can call the function passed as a func ptr:
...
your_callback_func(i, j);
...
The typedef has the name pf and it is for a function pointer that takes two integers as arguments and returns an integer.
typedef works as:
Define unknown type with known types.
So it defines function type that takes two int argument and return int.
Related
typedef int (*t_built)(t_cmds *, t_table *);
struct cmdline
{
char * reserved[7]; /* "echo pwd cd unset export exit env" */
t_built builtin[7];
}
How can I store my builtin functions into builtin array with same indexes as in reserved array. Can you help me to understand how this syntax works and for what declared typedef for function pointer.
Let's decompose the declarations:
int f(int);
declares f as a function taking an int and returning an int.
This can be written with parentheses (this is useless here but harmless):
int (f)(int);
The following declaration:
int *f(int);
declares f as a function taking an int and returning a pointer to an int.
This time, parentheses change the order of evaluation:
int (*f)(int);
declares f as a pointer to a function taking an int and returning an int.
typedef is used to define a type instead of a variable.
Finally the sequence:
typedef int (*f)(int);
f a[7];
declares a as an array of seven elements of type f, f describing a pointer to a function taking an int and returning an int.
By the way, there is a converter for that sort of things: cdecl: C gibberish ↔ English.
Here is the sample code
typedef int INT, *INTPTR, ONEDARR[10], TWODARR[10][10];
What does the above code means?
INT is the alias for int. Rest of the code what is happening?
The one-line typedef in the question is a shortcut for
typedef int INT;
typedef int *INTPTR;
typedef int ONEDARR[10];
typedef int TWODARR[10][10];
Then INT is an alias for type int.
INTPTR is an alias for type int *.
ONEDARR is an alias for type int [10].
TWODARR is an alias for type int [10][10].
(https://en.cppreference.com/w/c/language/typedef)
Consider the following declaration
int INT, *INTPTR, ONEDARR[10], TWODARR[10][10];
It declares four variables with type specifier int:
scalar variable INT
pointer *INTPTR
one-dimensional array ONEDARR[10]
and two-dimensional array TWODARR[10][10]
Then using the typedef
typedef int INT, *INTPTR, ONEDARR[10], TWODARR[10][10];
then the names of variables mean not objects but aliases for types that had the variables if they were declared without the typedef.
So INT means the type int, INTPTR means the type int *, ONEDARR means the type int[10], and TWODARR means the type int[10][10].
So now you have a choice whether to declare an array the following way
int a'10][10];
or to specify its type using an alias for the type of the array
TWODARR a;
Consider one more example.
Let's assume you have a function declaration
int f( int x, int y );
It has the type int( int, int ). Now you want to name this type that instead of this long record int( int, int ) to use a shorter record. Then you can use a typedef like
typedef int FUNC( int x, int y );
and as result the name FUNC now denotes the type int( int, int ).
typedef regularly works like: typedef <type> <type_alias>. But typedefs for function pointers seems to have different structure: typedef int (*fn)(char *, char *); - there is no type alias, just a single function signature.
Here is the example code:
#include <stdio.h>
typedef void (*callback)(int);
void range(int start, int stop, callback cb) {
int i;
for (i = start; i < stop; i++) {
(*cb)(i);
}
}
void printer(int i) {
printf("%d\n", i);
}
main(int argc, int *argv[])
{
if (argc < 3) {
printf("Provide 2 arguments - start and stop!");
}
range(atoi(argv[1]), atoi(argv[2]), printer);
}
So - why typedefs for function pointers are different?
The syntax for using typedef to define a function pointer type follows the same syntax as you would use for defining function pointers.
int (*fn)(char *, char *);
Defines fn to be a pointer to a function ...
typedef int (*fn)(char *, char *);
Defines fn to be a type that is a pointer to a function ...
It works the same. You just have to look at it in a slightly different way. typedef defines your own type name by putting it in exactly the place where the identifier of your variable would go without the typedef. So
uint8_t foo;
becomes
typedef uint8_t footype;
footype foo;
edit: so "R Sahu" was a bit faster and see his example for the same principle applied to function pointers.
C declaration syntax is much more complicated than type identifier, with examples like
T (*ap)[N]; // ap is a pointer to an N-element array
T *(*f())(); // f is a function returning a pointer to
// a function returning a pointer to T
Syntactically, typedef is treated as a storage class specifier like static or extern. So you can add typedef to each of the above, giving
typedef T (*ap)[N]; // ap is an alias for type "pointer to N-element array
typedef T *(*f())(); // f is an alias for type "function returning
// pointer to function returning pointer to T"
I want to convert the libusb.h into PureBasic code and now I have this line:
typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer);
What does this typedef do?
Later on there are lines like this:
void LIBUSB_CALL libusb_free_device_list(libusb_device **list, int unref_devices);
Thanks in advance!
LIBUSB_CALL is just a type annotation. It probably doesn't do anything.
This declares a type "f" that is a function pointer returning void and taking "params":
typedef void (*f)(params...)
libusb_transfer_cb_fn is a type representing a function pointer tacking a pointer to a libusb_transfer struct and returning nothing (void).
The syntax for typedef in C is peculiar. What you do is write an ordinary declaration:
int x, *y, z[2];
and then insert the keyword typedef in front. This tells the compiler that, for each variable declared, don't actually declare a variable; instead, make that a new name for the type that the variable would have had, if it were a variable. So:
typedef int x, *y, z[2];
makes x an alias for int, y an alias for int *, and z an alias for int [2].
If you take the typedef off the original line you get:
void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer);
(which is only syntactically valid if LIBUSB_CALL is a macro, probably some compiler-specific modifier like __stdcall or __fastcall), which is already a little peculiar because of C's need to parenthesize pointers-to-functions. But it would declare (and define) libusb_transfer_cb_fn as a variable of type "pointer to function taking one argument (the transfer thing) and returning void. So the typedef makes libusb_transfer_cb_fn an alias for that type.
The name obviously (well... :-) ) means: "callback function for libusb after a transfer operation".
The idea would be that a later bit of C code might read something like:
extern libusb_transfer_cb_fn abc_func;
which tells you that there's some global variable abc_func of type "pointer to libusb callback", or:
some_return_type xyz_func(libusb_transfer_cb_fn funcp, int a, char *b) {
struct libusb_transfer x;
... some code that fills in x ...
(*funcp)(&x);
}
typedef int (*P)(char *(*)());
int (*P)(char *(*)());
Both seems to be doing the same thing to me,what's the typedef there for?
The first declares a type called P that you can use in the declaration of other variables. The second declares a variable of that same type.
For illustrative purposes:
typedef int (*P)(char *(*)());
int main() {
int (*Q)(char *(*)());
P R;
}
In this example the variables Q and R have exactly the same type.
The typedef defines P to be a function pointer type. The second version defines P to be a function pointer.
A type can be used to declare variables. After
typedef int (*P)(char *(*)());
you can use
P p;
which will be equivalent to
int (*p)(char *(*)());
The simple answer would be you are creating a new datatype through typedef.
Let's take a simple example, in embedded system we use only unsigned numbers.
Now 1 way is I write
unsigned int xyz;
So here I would have to type unsigned everywhere.. What if I forget to type unsigned somewhere, it's very difficult to figure out that if the code is released. So simple way would be
typedef unsigned int uint;
So now you can use uint as a datatype. So whenever parser encounter uint, it would read it as unsigned int.
So in your case you can use P as a datatype in code. So Like in the first example
P xyz ;
would be parsed as
int (*xyz)(char *(*)());