Trying to understand function pointers in C

I am trying to understand function pointers and get confused. I saw a sorting example in K & R and several other similar examples. My main problem is what the computer actually does. I created a very simple program to try to see the basics. See the following:

#include <stdio.h> int func0(int*,int*); int func1(int*,int*); int main(){ int i = 1; myfunc(34,23,(int(*)(void*,void*))(i==1?func0:func1));//34 and 23 are arbitrary inputs } void myfunc(int x, int y, int(*somefunc)(void *, void *)){ int *xx =&x; int *yy=&y; printf("%i",somefunc(xx,yy)); } int func0(int *x, int *y){ return (*x)*(*y); } int func1(int *x, int *y){ return *x+*y; } 

The program either multiplies or adds two numbers depending on some variable (i in the main function - probably should be an argument in the main). fun0 multiplies two ints and func1 adds them.

I know this example is simple, but how to pass a pointer to a function is preferable to set a condition inside the myfunc function? that is, in myfunc have the following:

 if(i == 1)printf("%i",func0(xx,yy)); else printf("%i",func1(xx,yy)); 

If I did this, the result would be the same, but without using function pointers.

+4
source share
3 answers

Your understanding of how function pointers work is great. What you do not see is how the software system will benefit from the use of function pointers. They become important when working with components that do not know others.

qsort () is a good example. qsort will allow you to sort any array and don't really know what the array is. Therefore, if you have an array of structures, or rather pointers to structures, you will need to provide a function that could compare structures.

 struct foo { char * name; int magnitude; int something; }; int cmp_foo(const void *_p1, const void *_p2) { p1 = (struct foo*)_p1; p2 = (struct foo*)_p2; return p1->magnitude - p2->magnitude; } struct foo ** foos; // init 10 foo structures... qsort(foos, 10, sizeof(foo *), cmp_foo); 

Then the foos array will be sorted depending on the value field.

As you can see, this allows you to use qsort for any type - you need to provide a comparison function.

Another common use of function pointers is callbacks, for example, in a graphical interface. If you want the function to be called when the button is pressed, you must specify a pointer to the function for the GUI library when configuring the button.

+10
source

how the pointer to the function is passed, it is preferable to place the condition inside the myfunc function

Sometimes it is impossible to set a condition: for example, if you write a sorting algorithm, and you do not know that you are sorting ahead of time, you simply cannot set a condition; The function pointer allows you to “plug” a piece of calculation into the main algorithm without jumping over hoops.

How the mechanism works, the idea is simple: all your compiled code is in the program memory, and the CPU executes it, starting from a specific address. There are instructions to make the CPU jump between addresses, remember the current address and jump, remember the address of the previous jump and return to it, etc. When you call a function, one of the things the processor needs to know is its address in program memory. The function name represents this address. You can directly specify this address, or you can assign it to a pointer to indirect access. This is similar to accessing values ​​through a pointer, except that in this case you are indirectly accessing the code, not the data access.

+2
source

First of all, you can never give a function pointer a pointer to a function of another type. This behavior is undefined in C (C11 6.5.2.2).

A very important tip when working with function pointers is always to use typedefs.

So your code can / should be rewritten as:

 typedef int (*func_t)(int*, int*); int func0(int*,int*); int func1(int*,int*); int main(){ int i = 1; myfunc(34,23, (i==1?func0:func1)); //34 and 23 are arbitrary inputs } void myfunc(int x, int y, func_t func){ 

To answer the question, you want to use function pointers as parameters when you do not know the nature of the function. This is common when writing general algorithms.

Take the standard C function bsearch() as an example:

 void *bsearch (const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); ); 

This is a general binary search algorithm that searches for any form of one-dimensional binding containing unknown data types, such as user types. Here, the “compare” function compares two objects of unknown nature for equality, returning a number to indicate this.

"The function must return an integer less than, equal to, or greater than zero if the key object is considered correspondingly smaller to match or be greater than the element of the array."

The function is written by the caller who knows the nature of the data. In computer science, this is called a “function object” or sometimes a “functor”. This is commonly found in object oriented design.

Example (pseudo code):

 typedef struct // some user-defined type { int* ptr; int x; int y; } Something_t; int compare_Something_t (const void* p1, const void* p2) { const Something_t* s1 = (const Something_t*)p1; const Something_t* s2 = (const Something_t*)p2; return s1->y - s2->y; // some user-defined comparison relevant to the object } ... Something_t search_key = { ... }; Something_t array[] = { ... }; Something_t* result; result = bsearch(&search_key, array, sizeof(array) / sizeof(Something_t), // number of objects sizeof(Something_t), // size of one object compare_Something_t // function object ); 
+1
source

Source: https://habr.com/ru/post/1403484/


All Articles