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.
Related
I have an assignment to typedef function pointers which can point to main function. I tried something like this but I'm not sure if it's viable.
typedef mainPtr(*f[])(int, char**);
The thing that bothers me is that array size is not defined. How would you do this?
The type of main (in the form you want) is int main(int, char **).
A pointer to that is int (*main)(int, char **).
An array of those is int (*main[])(int, char **).
A typedef of that is typedef int (*mainPtr[])(int, char **);.
Whether you need a size for the array depends on how you will use the type. If you define and initialize an object of this type, its array size will be completed by counting the initializers. For example:
mainPtr p = { main, NULL };
will create an array with two elements.
In other uses, such as declaring a function parameter with this type, you may not need the array to be complete. An array function parameter is automatically adjusted to be a pointer, so the size is discarded anyway. However, if you wish, you could include the size in the typedef.
The syntax is easier if you typedef function itself:
typedef int mainfunc(int, char **);
Then you can use the "normal" pointer syntax:
/* definition of the function pointer*/
mainfunc *mainptr;
/* definitions of the function pointer arrays*/
mainfunc *mainptrarray[5];
mainfunc *mainptrarray1[] = {foo, bar, NULL};
I know about typedef in C, but I got confused when I saw a declaration in the K&R book. The declaration is
typedef int (*PFI) (char *,char *)
What does it mean? What is PFI and how can we use it in our program?
Breaking it down, PFI is a pointer:
*PFI
To a function:
(*PFI)()
Which takes two arguments of type char *:
(*PFI)(char *, char *)
And returns an int:
int (*PFI)(char *, char *)
And declared as an alias of that type:
typedef int (*PFI)(char *, char *);
You could use it if you had a function that matches this pointer type, i.e:
int foo(char *x, char *y)
{
...
}
Then you can assign a pointer to the function to a variable of type PFI:
PFI f = &foo;
were you reading about pointer to functions?
If yes, then PFI is just a placeholder. It can be whatever name you give, it is just a function name. I guess it could mean "Preferred Function Interface" but that is just a guess.
so let's say you write a very crude code something like
typedef bool (*write_X_Bytes) (uint32 count, char *buffer);
then you can use it as a type in C since you used typedef in front of it like
write_X_Bytes print_line, print_word;
basically you give a prototype to user or whoever wants to use this code about parameters and return. You can checkout Linux kernel driver code for GPIO for real life usecase.
Basic rules of pointer declarations:
T *p; // p is a pointer to T
T *ap[N]; // ap is an N-element array of pointers to T
T *fp(); // fp is a function returning a pointer to T
T (*pa)[N]; // pa is a pointer to an array of T
T (*pf)(); // pf is a pointer to a function returning T
In both expressions and declarators, the subscript [] and function call () operators have higher precedence than the unary dereference * operator, so an expression or declarator like *f() is parsed as *(f()) - you are dereferencing the result of f. If you want to dereference f before calling it, you have to explicitly group the * operator with it - (*f)().
The way to read a hairy declaration is to start with the leftmost identifier and work your way out according to the rules above, applying them recursively to any function parameters.
If you have a function that uses abstract declarators in the parameter list like this one, just remember:
T * -> T *λ
T *[N] -> T *λ[N]
T (*)[N] -> T (*λ)[N]
T *() -> T *λ()
T (*)() -> T (*λ)()
where λ represents where the identifier would normally go.
So, the way to read this declaration is as
PFI -- PFI
typedef PFI -- is a typedef name for
typedef *PFI -- pointer to
typedef (*PFI) ( ) -- a function taking
typedef (*PFI) ( ) -- unnamed parameter
typedef (*PFI) ( * ) -- is a pointer to
typedef (*PFI) (char * ) -- char
typedef (*PFI) (char *, ) -- unnamed parameter
typedef (*PFI) (char *, *) -- is a pointer to
typedef (*PFI) (char *,char *) -- char
typedef int (*PFI) (char *,char *); -- returning int
In less formal terms, PFI is an alias for the type "pointer to a function taking two char * parameters and returning int".
So how would we use this?
A common use is declaring callbacks in function parameter lists:
void foo( char *foo, char *bar, PFI callback )
{
int x = callback( foo, bar );
...
}
That's a little easier to read than
void foo( char *foo, char *bar, int (*callback)(char *, char *) )
{
int x = callback( foo, bar );
...
}
It's also useful for declaring arrays or struct members:
int func1( char *x, char *y ) { ... }
int func2( char *a, char *b ) { ... }
...
struct s {
char *x;
char *y;
PFI f;
} blah = {"foo", "bar", func1};
PFI callbacks[] = { func1, func2, ... };
Again, that's a bit cleaner than writing
struct s {
char *x;
char *y;
int (*f)(char *, char *);
};
or
int (*callbacks[])(char *, char *) = { func1, func2, ... };
But...
"Being a bit cleaner" is not, by itself, sufficient reason to hide the type behind a typedef. You use a typedef to abstract away details about a type that the user of the type doesn't need to know about in order to use it.
For example, consider the FILE type in stdio.h. There is an entire API supporting the FILE type, such that you never need to know what it looks like under the hood.
In our case, however, we have to know that a PFI is a pointer to a function expecting two char * arguments and returning an int in order to use it. Using the typedef name saves a few keystrokes, but it also creates a "leaky" abstraction, since details about the type have to "leak" out to the programmer. In this case, it's honestly better to forego the typedef altogether and use the "naked" declaration.
https://cdecl.org/ says "declare PFI as pointer to function (pointer to char, pointer to char) returning int". That website didn't like the initial typedef but that makes it a type so you can you write:
PFI fp = f;
where f would have the prototype:
int f(char *, char *);
PFI just means "Pointer to a function returning int". It's a fast way to create a type that can be used quickly in code, because otherwise the syntax is complicated.
As one example, it's very useful for callback interfaces. You may want to define something like PFContext_t as a pointer to a function taking certain arguments and returning a context pointer. Then you can use the typedef in your data (if, for instance, you want to keep the pointer in a structure), and you can use the typedef in the arguments to a function called by the client, setting the callback.
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.
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 *(*)());