Programmers often need to implement callback. This article discusses the basic principles of function pointers and describes how to use function pointers for callback. Note that this is intended for common functions, excluding class member functions that fully depend on different syntaxes and Semantic Rules (class member pointers will be discussed in another article ).
Declare function pointer
A callback function is a function that a programmer cannot explicitly call. It is called by passing the callback function address to the caller. To implement callback, you must first define the function pointer. Although the defined syntax is a bit incredible, if you are familiar with the general method of function declaration, you will find that the declaration of function pointers is very similar to that of function declaration. See the following example:
Void F (); // function prototype
The preceding statement declares a function. If no parameter is input, void is returned. The function pointer declaration method is as follows:
Void (*)();
Let's analyze that the asterisks in the left Circular Arc are the key to function pointer declaration. The other two elements are the return type (void) of the function and the entry parameter in the incircle arc (in this example, the parameter is null ). Note that no pointer variable is created in this example-only the variable type is declared. Currently, you can use this variable type to create a type definition name and use the sizeof expression to obtain the size of the function pointer:
// Obtain the size of the function pointer
Unsigned psize = sizeof (void (*)());
// Define the function pointer declaration type
Typedef void (* PFV )();
PFV is a function pointer that points to a function without any input parameter and returns class behavior void. Using this type definition name can hide complex function pointer syntax.
The pointer variable should have a variable name:
Void (* p) (); // P is a pointer to a function.
P is a pointer to a function. This function has no input parameter and the return value type is void. The asterisk in the arc on the left is the pointer variable name. With pointer variables, you can assign values. The value contains the function name that matches the signature and the return type. For example:
Void func ()
{
/* Do something */
}
P = func;
The value assignment of P can be different, but it must be the address of the function, and the signature and return type are the same.
Pass the callback function address to the caller.
Now we can pass p to another function (caller)-Caller (), which calls the function pointed to by P, and the function name is unknown:
Void caller (void (* PTR )())
{
PTR ();/* call the function pointed to by PTR */
}
Void func ();
Int main ()
{
P = func;
Caller (p);/* pass the function address to the caller */
}
If different values are assigned to P (different function addresses), the caller will call functions with different addresses. Assign values can occur at runtime, so that you can achieve dynamic binding.
Call Specification
So far, we have only discussed function pointers and callbacks, but have not paid attention to the ansi c/C ++ compiler specifications. Many compilers have several call specifications. For example, in Visual C ++, you can add _ cdecl, _ stdcall, or _ Pascal before the function type to indicate its call specifications (default value: _ cdecl ). C ++ builder also supports the _ fastcall call specification. The call specification affects the given function name generated by the compiler, the sequence of parameter passing (from right to left or from left to right), and the responsibility for Stack cleaning (caller or called) and parameter transfer mechanism (stack, CPU register, etc ).
It is important to regard the call specification as part of the function type. Incompatible call specifications cannot be used to assign addresses to function pointers. For example:
// The called function uses int as the parameter and INT as the return value.
_ Stdcall int callee (INT );
// Call a function with the function pointer as the parameter
Void caller (_ cdecl int (* PTR) (INT ));
// Illegal operation of the called function address in P's Enterprise Image Storage
_ Cdecl int (* p) (INT) = callee; // Error
The pointer P and callee () types are incompatible because they have different call specifications. Therefore, the caller's address cannot be assigned to the pointer P, although the two have the same return value and parameter column.