Function Pointers
Functions also have their own addresses; the function name/&function name is the address of the function.
1.1 Basic Form
In the study of array pointers, we learned that
int arr[5];int (*pa)[5] = &arr;//pa is an array pointer
The type of pointer variable pa is int(*)[5].
So what is the form of a function pointer?
void test(char* str){}int main(){ void (*pt)(char*) = test; //pt is a function pointer return 0;}
pt’s type is void (*)(char*).
Which of the following codes can store the address of a function?
void (*pfun1)();void *pfun2();
Answer: pfun1 can store it.
pfun1 first combines with *, indicating that pfun1 is a pointer pointing to a function with no parameters, and the return type is void.
pfun2 first combines with () to determine it as a function returning an int* type.
So how do we write a function pointer?
int Add(int x, int y){ return x + y;}
Taking the Add function as an example, it has two int type parameters, and the return type is int.
The corresponding function pointer is of type int(*)(int,int).
int (*pf)(int, int) = Add;
By following these steps, you can correctly write a function pointer:
(1) Determine the function’s return type.
(2) Determine the function’s parameter types and count.
(3) Remove the variable names from the function parameter types and place them in parentheses.
(int x,int y) removes x, y, giving (int,int).
(4) Prefix with the function’s return type.
(5) Finally add (*) and the function pointer variable name.
Note that the parentheses around (*pf) cannot be omitted, otherwise the compiler will report an error.
Removing the parentheses would be equivalent to a function declaration, making assignment impossible.
1.2 Calling Functions with Function Pointers
As shown in the figure below, once we define a function pointer,
we can access the original function through the pointer.
At this point, (*pf) is actually equivalent to my_test.
We can call the previously mentioned Add function using 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;}
As we can see, both sum and sum1 correctly called the function.
Since 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, you can use them without *; however, when using *, parentheses must be added!
1.3 Two Peculiar Codes
Peculiar Code 1
(*(void (*)())0)();
Here, 0 is just an example; we cannot normally access the address 0.
When seeing this code, are you a bit confused?
Don’t worry, let’s analyze it slowly!
Peculiar Code 2
void (*signal(int , void(*)(int)))(int);
In plain language, the signal function takes a void(*)(int) function pointer as a parameter and also returns 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 with pf pointer return 0;}
“Is there really no way to simplify this peculiar code?”
Of course! That is to use typedef to give the void(*)(int) pointer a new name!
typedef void(*pf_t)(int);// Name void(*)(int) as 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
Now our code can be simplified.
void ( *signal( int, void(*)(int) ) )(int);// Source code // Simplified pf_t signal(int,pf_t);
Isn’t this much easier to distinguish?
2 Function Pointer Arrays
2.1 Basic Form
Since function pointers are also a pointer type, we can use an array of pointers to store them.
Prerequisite: The parameter types and return types of these functions must be the same.
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){// Function pointer array int (*pfArr[4])(int, int) = {Add, Sub, Mul, Div};
Compared to 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 function pointer array allows us to access each function in array form.
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){}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: Implement a calculator.
Menu: Use numbers to select the operation type.
Method: Use switch/case statements to implement function calls.
End: Use do/while for multi-input and to 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){}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("Exiting 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 optimize it using function pointers.
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 called a transfer table do { menu(); printf("Please select:>"); scanf("%d", &input); if (input == 0) { printf("Exiting 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 redundancy of writing input prompts, scanf, and different function calls in each case statement.
Try running it!
2.3 Pointer to Function Pointer Array
A function pointer array is an array, and an array can be stored using a pointer to the array.
A pointer to a function pointer array is a pointer that points to an array where each element 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 that points to a function with two int parameters and returns a function pointer that points to a function with one int parameter and returns int. Which of the following is correct?
A. int (*(*F)(int, int))(int)B. int (*F)(int, int)C. int (*(*F)(int, int))D. *(*F)(int, int)(int)
Step by step analysis of the requirements of the question.
The function pointer points to a function with two int types, i.e., (int,int), all ABCD qualify, cannot be excluded.
Carefully examine, D’s type is incomplete, directly exclude it.
Returns a function pointer, and that pointer points to a function with one int parameter and returns int.
B is a function pointer, returning type is int, incorrect.
C’s return value is int* type, incorrect.
A option, removing the function pointer F leaves int (*)(int), which meets the question’s requirements.
Conclusion
Did you learn anything?
*Note: This article is organized from the internet, copyright belongs to the original author. If the source information is incorrect or infringes rights, please contact us for deletion or authorization matters.
