Detailed explanation of C language function pointer

C language function pointer

1, What is a function pointer

1. Understand function pointers

Function pointer. First, according to its name, we can probably know that it is a pointer. What kind of pointer is it? Is a special pointer related to a function.

We know that int*p is a pointer to an int variable and char*p is a pointer to a char variable. It is not difficult to understand that a function pointer is a pointer to a function.

	int arr[10]={0};
	int *p = arr;

We know that in an array, the array name is the address of the first element.

So try to guess what the address of the function is like.

We might as well print it to see what the results are like.

int add(int x, int y)
{
	return x + y;
}
int main()
{
	printf("%p\n",&add);
	printf("%p\n",add);
	return 0;
}

The results are as follows:

Conclusion: the function name of the function is the address of the function.

2. How to define function pointers and how to use them

Find out the address of the function and the function of the function pointer, so how to define a function pointer?

First, the function has three elements: function name, function parameter, function return type, and function pointer is a pointer, so first, we ensure that the function name is combined with the * sign first, because in the operation order of c language operators, [] has higher priority than *, so we use () to solve this problem: (* pf), and then we consider the parameters of add function, int x, int y, It is two integer parameters, so we can write (* add) (int), and the return type is int, so after improvement, we get:

int (*pf)(int int)=add;

We can get a format to define the function pointer: return type (* pointer variable name) (function parameter type) = function name;

So how to call a function through pointer access after defining a function pointer?

We know that if you want to access the content of an element through a pointer, you need to dereference access through *, so it is inferred that you can use the function pointer: (* pf)(x,y).

However, in fact, when the function pointer is called, the * sign on the left of pf has no practical significance. Adding or not adding it will not affect the result, which makes it more convenient for us to use the function pointer: pf(x,y); You can use the add function.

3. Deepen understanding of function pointers

After understanding the concept of function pointer, we deepen our understanding through two pieces of complex function pointer code.

//Code 1:	
(*void(*)()0)();

//Code 2:
void(*signal(int,void(*)(int)))(int);

These two pieces of code are extracted from C defects and traps

At the first sight, I have a headache and have no way to start. To understand these two pieces of code, I need to understand the concept of type first:

We know:

char*pf;
// The type of the pointer variable pf is char*
int *pi;
// The type of the pointer variable pi is int*
int(*parr)[10];
// parr is an array pointer of type int(*)[10];
// According to the above example, it is not difficult to find out that the type of pointer variable is the rest after removing the pointer variable name
void(*pf)();
// We can get void(*) () by removing the pointer variable name pf, which is the type of the function pointer

Then it is not difficult for us to understand the first line of code:

  • First (* a type 0) is to convert the 0 mandatory type to a type. In this string of code, it is a function pointer that forcibly converts 0 to void(*) ().
  • Secondly, the outer parentheses are actually a call to the function through the function pointer to dereference the 0 address and go to the function at the 0 address. The called function has no parameters and the return type is void.

Let's look at the second code:

  • According to the above rule, void(*)(int) is the type of a function pointer.

  • The function name is signal. There are two parameters. One is an int parameter, and the other is a void(*)(int) function pointer.

  • Then the outermost layer must be the return type of the pointer function: void(*)(int).

  • So this code is actually a declaration of the function pointer: the signal function has two parameters, the first is the int type, the second is the void()(int) function, and the return value type is the void()(int) function pointer type.

    In fact, these two sections of code are just like this. When we analyze this complex function pointer code, as long as we grasp the three elements, the function name, parameters and return value of the function, all the problems are not complicated.

2, Function pointer array

1. How to understand function pointer array

Array is a space for storing data of the same type. We know that pointer array can be used to store multiple pointers, for example:

int* arr[5];

Store the addresses of multiple functions in an array, then this array is the function pointer array:

int(*Parr[5])(int)

Through analysis, the priority of "[]" in the first bracket is higher than *, so Parr is combined with [] to form an array. The content after removing the asterisk is the type of array storage, that is, the function pointer of type int(*)(int).

2. Purpose of function pointer array

In some special cases, when using ordinary function call methods will lead to code redundancy, we can use function pointer array.

For example: simply write a calculator

Generally, we use the do while() statement with switch to complete the branch loop, so as to control the function of the calculator:

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  ****\n");
	printf("****** 2.sub  ****\n");
	printf("****** 3.mul  ****\n");
	printf("****** 4.div  ****\n");
	printf("****** 0.exit ****\n");
	printf("******************\n");

}

int main()
{
    int x,y;
    int res=0;
	int input = 0;
	do
	{
		menu();
		printf("Please select-\n");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			printf("Enter two numbers\n");
            scanf("%d%d",&x,&y);
            res=add(x,y);
            printf("The result is:%d",ret);
			break;
		case 2:
			printf("Enter two numbers\n");
            scanf("%d%d",&x,&y);
            res=sub(x,y);
            printf("The result is:%d",ret);
			break;
		case 3:
			printf("Enter two numbers\n");
            scanf("%d%d",&x,&y);
            res=mul(x,y);
            printf("The result is:%d",ret);
			break;
		case 4:
			printf("Enter two numbers\n");
            scanf("%d%d",&x,&y);
            res=div(x,y);
            printf("The result is:%d",ret);
			break;
        case 0:
            printf("Exit calculator\n");
            break;
		default:
			printf("Selection error\n");
			break;
		}
	} while (input);
	return 0;
}

But in this way, the code will appear redundant, and the output and input will be repeated many times. Obviously, this is not the optimal solution.

Therefore, we can choose to use the function pointer array. We define a function pointer array at the beginning of the main function, load the four functions of addition, subtraction, multiplication and division into the array, and call the functions in the function pointer array according to the input value.

int main()
{
	int input = 0;
	int x = 0, y = 0, ret = 0;
	do
	{
		menu();
		printf("Please select-\n");
		scanf("%d",&input);
		int(*pfArr[5])(int, int) = { 0,add, sub, mul, div };
        //Define the function pointer array pfArr, set the first element to 0, corresponding to the value of input
		if (input == 0)
		{
			printf("Exit calculator\n");
		}
		else if(input >= 1 && input <= 4)
		{
			printf("Enter two operands\n");
			scanf("%d%d",&x,&y);
			//Call of function pointer array
			ret=pfArr[input](x,y);
			printf("%d\n",ret);
		}
		else
		{
			printf("Selection error\n");
		}
	} while (input);
	return 0;
}

After using the function pointer array, the code is obviously more refined. Is there any other method besides using the function pointer array?

When we encounter coupled code that is repeated many times, we usually use the method of encapsulating functions to simplify the code. Similarly, we can call these four function functions through another function:

int add(int x, int y) //int(*)(int int)
{
	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  ****\n");
	printf("****** 2.sub  ****\n");
	printf("****** 3.mul  ****\n");
	printf("****** 4.div  ****\n");
	printf("****** 0.exit ****\n");
	printf("******************\n");

}
//
void Calc(int(*pf)(int, int))  //The parameter here is the type of function pointer we call
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("Please enter two operands:\n");
	scanf("%d%d", &x, &y);
	ret = pf(x, y);//Calling a function through a pointer
	printf("%d\n",ret);
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("Please select-\n");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			Calc(add);
			break;
		case 2:
			Calc(sub);
			break;
		case 3:
			Calc(mul);
			break;
		case 4:
			Calc(div);
			break;
		default:
			printf("Selection error\n");
			break;
		}
	} while (input);
	return 0;
}

Receive a function pointer through Calc custom function. Calling different function functions in Calc function is also a method.

3. Pointer of function pointer array

According to his name, we can conclude that he is a pointer and a pointer to an array. What kind of array? Is a special array of function pointers.

We know how to define an array pointer: int (*Parr)[10]

So how to define the pointer of a function pointer array?

  • First, it is a pointer, array pointer, so we must first ensure that the pointer name and * are combined first.

  • Secondly, it points to the array containing function pointers, so it should point to the array of function pointers.

    int add(int x,int y)
    {
    	return x+y;
    }
    int main()
    {
        int(*Padd)(int,int)=add;
        //Function pointer padd
        int(*paddarr[5])(int,int);
        //Function pointer array paddarr
        paddarr[0]=add;
        
        
        int(*(*ppaddarr)[5])(int,int)=&paddarr;//Pointer to function pointer array
        //Pointer to function pointer array ppaddarr
        return 0;
    }
    

Keywords: C

Added by markspec87 on Fri, 24 Dec 2021 18:09:16 +0200