Pointer advanced fifth stop 🚏: Function pointer
Click on my home page to review the contents of the first four stations~
1 function pointer
Functions also have their own addresses. Function name / & function name is the address of the function
1.1 basic form
stay Array pointer In our study, we learned
int arr[5]; int (*pa)[5] = &arr;//pa is an array pointer
- The pointer variable pa is of type int(*)[5]
So what is the form of function pointer?
void test(char* str) {} int main() { void (*pt)(char*) = test; //pt is a function pointer return 0; }
- The type of pt is void (*)(char *)
Which of the following code has the ability to store the address of the function?
void (*pfun1)(); void *pfun2();
Answer: pfun1 can be stored
-
Pfun1 is first combined with * to explain that pfun1 is a pointer to a function. The pointed function has no parameters and the return value type is void
-
pfun2 is first combined with () to determine that it is a function with a return value of int *
So, how to write a function pointer?
int Add(int x, int y) { return x + y; }
Take the Add function as an example. It has two formal parameters of type int, and the return type is int
The corresponding function pointer is of type int(*)(int,int)
int (*pf)(int, int) = Add;
The function pointer can be written correctly according to the following steps
-
Determines the return type of the function
-
Determine the type and number of parameters of the function
-
Remove the variable name from the function parameter type and put it in parentheses
(int x,int y) remove X and y, i.e. (int,int)
-
Add the return type of the function before it
-
Finally, add (*) and the function pointer variable name
It should be noted that the brackets of (* pf) cannot be omitted, otherwise the compiler will report an error
After removing the parentheses, it is equivalent to a function declaration and cannot be assigned
1.2 calling functions with function pointers
As shown in the figure below, when we define a function pointer
You can access the original function through a pointer
At this time (* pf) is actually equivalent to my_test
We can call the Add function mentioned above through the function pointer
int Add(int x, int y) { return x + y; } int main() { int (* pf)(int, int) = Add; int sum = (*pf)(2,3); int sum1 = pf(2, 3); int sum2 = Add(2, 3); printf("%d\n", sum); printf("%d\n", sum1); printf("%d\n", sum2); return 0; }
You can see that both sum and sum1 call this function correctly
Because we have transferred the address of Add to the pf pointer, the function name Add and the pointer pf are actually equivalent
Therefore, when using function pointers, they can be used without *. But be sure to add parentheses when you put * in it!
1.3 two wonderful codes
Wonderful code 1
(*(void (*)())0)();
0 here is only an example. We cannot access the address of 0 during normal use
Is it a little confused when you see this code?
Don't worry, let's analyze a wave slowly!
Wonderful code 2
void (*signal(int , void(*)(int)))(int);
In other words, a void(*)(int) function pointer is passed in the signal function, and the return value is also a void(*)(int) function pointer!
void fun(int num) { printf("fun-->%d\n", num); } void ( *signal( int, void(*)(int) ) )(int); int main() { void(*pf)(int);//Define a function pointer pf = signal(100, fun); //Pass parameters to the signal function and receive them with pf pointer return 0; }
"This code 2 is really wonderful. Is there no way to turn it into human words? (simplify it)"
Of course! That is to use the typedef function to give a new name to the void(*)(int) pointer!
typedef void(*pf_t)(int); //Name void(*)(int) pf_t
void(*p)(int);//p is the name of the function pointer variable typedef void(*pf_t)(int);//pf_t is a new type name
So our code can be simplified
void ( *signal( int, void(*)(int) ) )(int);//source code //After simplification pf_t siganal(int,pf_t);
Is it easier to tell?
2 function pointer array
2.1 basic form
Since the function pointer is also a pointer type, we can use the pointer array to store it
- Premise: the parameter types and return types of these functions are consistent
int Add(int x, int y) { return x + y; } int Sub(int x, int y) { return x - y; } int Mul(int x, int y) { return x * y; } int Div(int x, int y) { return x / y; } //Function pointer array int (*pfArr[4])(int, int) = {Add, Sub, Mul, Div};
Instead of writing multiple function calls separately
//Multiple function calls int (*pf1)(int,int) = Add; int (*pf2)(int, int) = Sub; int (*pf3)(int, int) = Mul; int (*pf4)(int, int) = Div;
The array of function pointers allows us to access each function as an array
int Add(int x, int y) { return x + y; } int Sub(int x, int y) { return x - y; } int Mul(int x, int y) { return x * y; } int Div(int x, int y) { return x / y; } int main() { int (*pfArr[4])(int, int) = {Add, Sub, Mul, Div};//Function pointer array int i = 0; for (i = 0; i < 4; i++) { //int ret = (*pfArr[i])(8, 4); int ret = pfArr[i](8, 4); printf("%d\n", ret); } return 0; }
This also simplifies our code
2.2 calculator implementation
2.2.1 switch statement
- Objective: to realize a calculator
- Menu: select operation type with numbers
- Method: use switch/case statement to realize function call
- End: use do/while to realize multiple groups of input and end the program
int Add(int x, int y) { return x + y; } int Sub(int x, int y) { return x - y; } int Mul(int x, int y) { return x * y; } int Div(int x, int y) { return x / y; } void menu() { printf("**********************************\n"); printf("***** 1. add 2. sub *****\n"); printf("***** 3. mul 4. div *****\n"); printf("***** 0. exit *****\n"); printf("**********************************\n"); } int main() { int input = 0; int x = 0; int y = 0; int ret = 0; do { menu(); printf("Please select:>"); scanf("%d", &input); switch (input) { case 1: printf("Enter 2 operands:>"); scanf("%d %d", &x, &y); ret = Add(x, y); printf("ret = %d\n", ret); break; case 2: printf("Enter 2 operands:>"); scanf("%d %d", &x, &y); ret = Sub(x, y); printf("ret = %d\n", ret); break; case 3: printf("Enter 2 operands:>"); scanf("%d %d", &x, &y); ret = Mul(x, y); printf("ret = %d\n", ret); break; case 4: printf("Enter 2 operands:>"); scanf("%d %d", &x, &y); ret = Div(x, y); printf("ret = %d\n", ret); break; case 0: printf("Exit calculator\n"); break; default: printf("Selection error\n"); break; } } while (input); return 0; }
This method requires a lot of repetitive code, and the code length is very long 😵
We can use function pointers to optimize it
2.2.2 function pointer form
int main() { int input = 0; int x = 0; int y = 0; int ret = 0; int (*pfArr[5])(int, int) = {0, Add, Sub, Mul, Div}; //pfArr is an array of function pointers, also known as a transfer table do { menu(); printf("Please select:>"); scanf("%d", &input); if (input == 0) { printf("Exit calculator\n"); break; } else if (input >= 1 && input <= 4) { printf("Enter 2 operands:>"); scanf("%d %d", &x, &y); ret = pfArr[input](x, y); printf("ret = %d\n", ret); } else { printf("Selection error\n"); } } while (input); return 0; }
This avoids the code redundancy caused by writing input prompt, scanf and different function calls in each case statement
Try it!
2.3 pointer to function pointer array
The function pointer array is an array. The array can use the array pointer to store the address
- Pointer to array of function pointers: is a pointer
- The pointer points to an array, and each element of the array is a function pointer
int Add(int x, int y) { return x + y; } int main() { int (*pa)(int, int) = Add;//Function pointer int (* pfA[4])(int, int);//Array of function pointers int (* (*ppfA)[4])(int, int) = &pfA; //ppfA is a pointer that points to an array of function pointers return 0; }
3. Related exercises
Define a function pointer. The pointed function has two int parameters and returns a function pointer. The returned pointer points to a function with one int parameter and returns int? Which of the following is true?
A. int (*(*F)(int, int))(int) B. int (*F)(int, int) C. int (*(*F)(int, int)) D. *(*F)(int, int)(int)
Analyze the requirements of the topic step by step
-
The function pointed to by the function pointer has two int types, namely (int,int), both of which are found in ABCD and cannot be excluded
-
Take a closer look. The type of D is not completely written. It is directly excluded
-
Returns a function pointer that points to a function that has an int parameter and returns int
B is a function pointer, the return type is int, error
The return value of C is of type int, error
-
After the function pointer F is removed from option A, int (*)(int) remains, which is in line with the meaning of the question
epilogue
The knowledge point of function pointer is the first contact 🧐
Have you failed? 😂
Next Station 🚃: Callback function