Advanced C Language: Function Pointers Explained

Click the blue words
Follow us

Function Pointers

Functions also have their own addresses; the function name/&function name is the address of the function.

Advanced C Language: Function Pointers Explained

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.

Advanced C Language: Function Pointers Explained

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.

Advanced C Language: Function Pointers Explained

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.

Advanced C Language: Function Pointers Explained

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!

Advanced C Language: Function Pointers Explained

Peculiar Code 2

void (*signal(int , void(*)(int)))(int);

Advanced C Language: Function Pointers Explained

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!

Advanced C Language: Function Pointers Explained

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.

Advanced C Language: Function Pointers Explained

Advanced C Language: Function Pointers Explained
Click to read the original text for more information

Leave a Comment