What exactly is the callback function ?, What is the callback function?
I was confused when I saw the callback function today. I found a lot of Search Engine information, but I did not understand it after reading "c and pointer.
Briefly describe what is a callback function:
The user passes a function pointer as a parameter to other functions, and the latter calls back the user's function. If a function can execute different types of work at different times or the execution can only be defined by the function caller, you can use the callback function. The callback function cannot know the type of the Compare value. Therefore, the parameter type is declared as void *. Indicates a pointer to an unknown type. You can use the function pointer to implement the callback function. A pointer pointing to the callback function is passed as a parameter to another function, which is used to call the callback function.
Too many definitions may not be quite clear. Let's talk about it in a few cases.
When we look for a number in the linked list, we generally write as follows:
1 Node *search_list( Node *node, int const value ) 2 { 3 while ( NULL != node ){ 4 if ( node->value == value ){ 5 break; 6 } 7 node = node->link; 8 } 9 10 return node;11 }
In this way, we can only find the number must be of the int type. When it is changed to another type, we cannot use this function, but re-write a function, they have too many repeated code. Let's see how to use the callback function.
Callback Function search:
1 int compare_int( void const *a, void const *b )2 {3 if ( *( int * )a == *( int * )b ){4 return 0;5 }6 7 return 1;8 }
1 Node * search_list (Node * node, void const * value, 2 int (* compare) (void const *, void const *)) // function pointer 3 {4 while (node! = NULL) {5 if (compare (& node-> value, value) = 0) // 6 equal break; 7 node = node-> link; 8} 9 return node; 10}
In this way, the callback function can solve the above problem. We pass a function pointer (int (* compare) (void const *, void const *) as a parameter to the lookup function. The lookup function calls back the comparison function. When we need to execute different types of comparisons, we call this function properly. For example, when we perform integer search: search_list (root, & desired_value, compare_int); when we use character search: search_list (root, & desired_value, compare_char );. This is a simple application of the callback function. Of course, the callback function is not only used for these simple examples. For example, the library function qsort is implemented using the callback function.
The function prototype is as follows:
Void qsort (void * base, // string first address size_t num, // total number of sorting size_t width, // int (_ cdecl * compare) (const void *, const void *) // function pointer );
Library Function implementation:
Void qsort (void * base, // string first address size_t num, // total number of sorting size_t width, // int (_ cdecl * compare) (const void *, const void *) // function pointer );
{ char *lo, *hi; /* ends of sub-array currently sorting */ char *mid; /* points to middle of subarray */ char *loguy, *higuy; /* traveling pointers for partition step */ size_t size; /* size of the sub-array */ char *lostk[STKSIZ], *histk[STKSIZ]; int stkptr; /* stack for saving sub-array to be processed */ /* validation section */ _VALIDATE_RETURN_VOID(base != NULL || num == 0, EINVAL); _VALIDATE_RETURN_VOID(width > 0, EINVAL); _VALIDATE_RETURN_VOID(comp != NULL, EINVAL); if (num < 2) return; /* nothing to do */ stkptr = 0; /* initialize stack */ lo = (char *)base; hi = (char *)base + width * (num-1); /* initialize limits */ /* this entry point is for pseudo-recursion calling: setting lo and hi and jumping to here is like recursion, but stkptr is preserved, locals aren't, so we preserve stuff on the stack */recurse: size = (hi - lo) / width + 1; /* number of el's to sort */ /* below a certain size, it is faster to use a O(n^2) sorting method */ if (size <= CUTOFF) { __SHORTSORT(lo, hi, width, comp, context); } else { /* First we pick a partitioning element. The efficiency of the algorithm demands that we find one that is approximately the median of the values, but also that we select one fast. We choose the median of the first, middle, and last elements, to avoid bad performance in the face of already sorted data, or data that is made up of multiple sorted runs appended together. Testing shows that a median-of-three algorithm provides better performance than simply picking the middle element for the latter case. */ mid = lo + (size / 2) * width; /* find middle element */ /* Sort the first, middle, last elements into order */ if (__COMPARE(context, lo, mid) > 0) { swap(lo, mid, width); } if (__COMPARE(context, lo, hi) > 0) { swap(lo, hi, width); } if (__COMPARE(context, mid, hi) > 0) { swap(mid, hi, width); } /* We now wish to partition the array into three pieces, one consisting of elements <= partition element, one of elements equal to the partition element, and one of elements > than it. This is done below; comments indicate conditions established at every step. */ loguy = lo; higuy = hi; /* Note that higuy decreases and loguy increases on every iteration, so loop must terminate. */ for (;;) { /* lo <= loguy < hi, lo < higuy <= hi, A[i] <= A[mid] for lo <= i <= loguy, A[i] > A[mid] for higuy <= i < hi, A[hi] >= A[mid] */ /* The doubled loop is to avoid calling comp(mid,mid), since some existing comparison funcs don't work when passed the same value for both pointers. */ if (mid > loguy) { do { loguy += width; } while (loguy < mid && __COMPARE(context, loguy, mid) <= 0); } if (mid <= loguy) { do { loguy += width; } while (loguy <= hi && __COMPARE(context, loguy, mid) <= 0); } /* lo < loguy <= hi+1, A[i] <= A[mid] for lo <= i < loguy, either loguy > hi or A[loguy] > A[mid] */ do { higuy -= width; } while (higuy > mid && __COMPARE(context, higuy, mid) > 0); /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi, either higuy == lo or A[higuy] <= A[mid] */ if (higuy < loguy) break; /* if loguy > hi or higuy == lo, then we would have exited, so A[loguy] > A[mid], A[higuy] <= A[mid], loguy <= hi, higuy > lo */ swap(loguy, higuy, width); /* If the partition element was moved, follow it. Only need to check for mid == higuy, since before the swap, A[loguy] > A[mid] implies loguy != mid. */ if (mid == higuy) mid = loguy; /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top of loop is re-established */ } /* A[i] <= A[mid] for lo <= i < loguy, A[i] > A[mid] for higuy < i < hi, A[hi] >= A[mid] higuy < loguy implying: higuy == loguy-1 or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */ /* Find adjacent elements equal to the partition element. The doubled loop is to avoid calling comp(mid,mid), since some existing comparison funcs don't work when passed the same value for both pointers. */ higuy += width; if (mid < higuy) { do { higuy -= width; } while (higuy > mid && __COMPARE(context, higuy, mid) == 0); } if (mid >= higuy) { do { higuy -= width; } while (higuy > lo && __COMPARE(context, higuy, mid) == 0); } /* OK, now we have the following: higuy < loguy lo <= higuy <= hi A[i] <= A[mid] for lo <= i <= higuy A[i] == A[mid] for higuy < i < loguy A[i] > A[mid] for loguy <= i < hi A[hi] >= A[mid] */ /* We've finished the partition, now we want to sort the subarrays [lo, higuy] and [loguy, hi]. We do the smaller one first to minimize stack usage. We only sort arrays of length 2 or more.*/ if ( higuy - lo >= hi - loguy ) { if (lo < higuy) { lostk[stkptr] = lo; histk[stkptr] = higuy; ++stkptr; } /* save big recursion for later */ if (loguy < hi) { lo = loguy; goto recurse; /* do small recursion */ } } else { if (loguy < hi) { lostk[stkptr] = loguy; histk[stkptr] = hi; ++stkptr; /* save big recursion for later */ } if (lo < higuy) { hi = higuy; goto recurse; /* do small recursion */ } } } /* We have sorted the array, except for any pending sorts on the stack. Check if there are any, and do them. */ --stkptr; if (stkptr >= 0) { lo = lostk[stkptr]; hi = histk[stkptr]; goto recurse; /* pop subarray from stack */ } else return; /* all subarrays done */}
To better understand the callback function, let's write a qsort function (using Bubble Sorting)
Int char_compare (void const * c1, void const * c2) // comparison function {int a = * (int *) c1); int B = * (int *) c2); return a> B? 1: a <B? -1: 0;} void Swap (char * str1, char * str2, int size) {while (size --) {char tmp = * str1; * str1 = * str2; * str2 = tmp; str1 ++; str2 ++ ;}} void MyQsort (void * str, int len, int elen, int (* compare) (void const *, void const *) // sort algorithm written based on callback function {int I = 0; int j = 0; int flag = 1; for (I = 0; I <len-1; I ++) {for (j = 0; j <len-1-i; j ++) {if (compare (char *) str + j * elen, (char *) str + (j + 1) * elen)> 0) {flag = 0; Swap (char *) str + j * elen, (char *) str + (j + 1) * elen, elen) ;}} if (flag) return ;}}
I have read the example to explain the principle.:
In short, a callback function is a function called through a function pointer. If you pass the pointer (address) of a function as a parameter to another function, when this pointer is used to call the function to which it points, we will say this is a callback function. The callback function is called by another party when a specific event or condition occurs instead of by the implementer of the function. It is used to respond to the event or condition.
The callback function implements the following mechanisms:
(1) define a callback function;
(2) The party providing function implementation registers the function pointer of the callback function to the caller during initialization;
(3) When a specific event or condition occurs, the caller uses the function pointer to call the callback function to process the event.
After reading two examples, you should be able to understand the callback function. If you have any questions, please trust me. We recommend that you fully understand the pointer Section. This is a pointer.
References:
Jian th A. Reek translated by Xu Bo. c and pointer. People's post and telecommunications press. 2008