when do we use function pointers
I am trying to understand the existing code.
When do we actually go for function pointers? specially like the one below.
struct xx
{
char *a;
(*func)(char *a, void *b);
void *b;
}
struct xx ppp[] = { };
then check sizeof(ppp)/sizeof(*ppp);
when do w开发者_Python百科e go with such kind of approach?
sizeof array / sizeof *array
is a way of finding out how many elements are in an array. (Note that it must be an array rather than a pointer.) I'm not sure how that's related to your function pointer question.
Function pointers are used to store a reference to a function so that it can be called later. The key thing is that a function pointer needn't always point to the same function. (If it did, you could just refer to the function by name.)
Here's an example based on your code (although I could provide a better one if I knew what your code was supposed to do.
char *s1 = "String one";
char *s2 = "String two";
void f(char *a, void *b) {
/* Do something with a and b */
}
void g(char *a, void *b) {
/* Do something else with a and b */
}
struct xx {
char *a;
void (*func)(char *a, void *b);
void *b;
}
struct xx ppp[] = { {s1, f, NULL}, {s2, g, NULL} };
int main(int argc, char **argv) {
for (int i = 0; i < (sizeof ppp / sizeof *ppp); i++) {
ppp[i].func(ppp[i].a, ppp[i].b);
}
}
There are two major uses (that I know of) for function pointers in C.
1. Callbacks
You have some sort of event-driven framework (a GUI is one of the easiest examples), and the program wants to react to events as they happen. Now you can do that with an event pump, like
while (event *e = get_one_event()) {
switch (e->type) {
case EVT_CLICK:
...
}
}
but that gets tiring after a while. The other major alternative is callbacks. The program defines a bunch of functions to handle different events, and then registers them with the library: "when event X happens, call function Y" -- so of course, the library is going to receive a function pointer, and call it at the relevant time.
2. Objects (function tables / vtables)
If you've done OO in most other languages, this should be fairly easy for you to picture. Imagine an object as a struct that contains its members and then a bunch of function pointers (or, maybe more likely, its members and a pointer to another struct representing its class, that contains a bunch of function pointers). The function pointers in the table are the object's methods. GLib/GObject is a big user of this technique, as is the Linux kernel (struct file_operations
, struct device_driver
, struct bus_type
, and many many more). This lets us have an arbitrary number of objects with different behavior, without multiplying the amount of code.
When do we actually go for function pointers? specially like the one below.
You use function pointer when you want to make something more abstract. By example, suppose your application has a graphical toolbox with a certain number of buttons. Every button corresponds to an instance of a certain struct.
The button structure can contain a function pointer and a context:
typedef struct {
void (*press_button) (void *context);
void *context;
/* Here some other stuff */
} Button;
When the user clicks the button, the event is something like
void event_click (Button *b)
{
b->press_button(b->context);
}
The point in doing this is that you can use always the same structure for each button:
Button * create_button (void (*callback) (void *), void *context, /* other params */
{
Button *ret = malloc(sizeof(Button));
if (ret != NULL) {
ret->callback = callback;
ret->context = context;
/* Assign other params */
}
...
return ret;
}
So when you build your toolbox you probably do something like
Button * toolbox[N];
toolbox[0] = create_button(function1, (void *)data, ...);
toolbox[1] = create_button(function2, (void *)something, ...);
...
toolbox[N-1] = create_button(functionN, (void *)something_else, ...);
Also when you create some function pointer, always carry some contxt information (like I did with the context
field of the struct). This allows you to avoid global variables, thus you can get a robust and reentrant code!
Note: This method is awesome, but if you deal with C++ you may prefer to use object orientation and replace callbacks with derivaton from abstract classes. By doing this you also don't need to carry the context, since the class will do it for you.
Edit in answer of first comment:
The current code I am going through is related to file IO. setting an environment variable and creating symbolic links between files, copying data from one file to another, etc. I am not understanding why do we need to call these functions at run time using function pointers. we can as well call them directly.
In fact you can do what you need without using function pointers. If I do understand well your problem, you are trying to understand someone else's code, which is doing what you listed with function pointers.
Personally I don't use this feature unless I need it but if you post here some additional code maybe we can try to understand it better.
精彩评论