[C language] Pointer advanced fifth station, function pointer

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

Keywords: C C++

Added by Rdam on Wed, 26 Jan 2022 14:30:06 +0200