Pointer to function and pointer to function array of pointer to function callback function

1> Author: They said that there is #include on the corner of the street
2> Knowledge points: explanation of pointer functions and function pointers, application of function pointers: function pointer arrays and callback functions.
3>Development environment: vs 2022

foreword

When we learn C language, we will encounter array pointers, pointer arrays, function pointer arrays, pointer functions, function pointers and other knowledge points that give us headaches and are very cumbersome. But after understanding the essence of these knowledge points, it is not difficult to learn these contents.

1. Pointer function

The pointer function is essentially a function, but this function returns a pointer, which is actually not much different from the definition of our common functions.

1.1 Definition of pointer function

  • The way we often use function definition is (type name identifier (formal parameter list) {function body}) The general form is (for example):int ret(int x,int y) {}
  • The definition of the pointer function is actually the same, and the way we define it is also (type name identifier (parameter list) {function body}) , but the pointer type is used. The general form is (for example): int* ret(int x,int y) {} 或者 int *ret(int x,int y) {}How to write depends on personal habits, there is no difference.

From this point of view, it is actually relatively simple, and there is no big difference from the definition of ordinary functions, that is, there is an extra *, that's all.

1.2 Use of pointer functions

Pointer functions are often used in some specific scenarios, so it is a very important knowledge point.

  • Let's take an example, for example, we want to use malloc now (if you are not sure about malloc, you can see here: dynamic memory allocation ) to open up a space in memory, if we want to use realloc to expand later, but in order to increase the readability of the function, We define a pointer function to implement it:
int* Main_realloc(int* p, int n)
{
    
    
	if (p != NULL)
	{
    
    
		int* tmp = (int*)realloc(p, n);
		if (tmp != NULL)
		{
    
    
			p = tmp;
		}
		else
		{
    
    
			printf(扩容失败);
		}
	}
	else
		{
    
    
			printf(扩容失败);
		}
	//************
	//函数体
	//对内存的一些操作
	//***********
	return p;
}
int main()
{
    
    
	int* p = (int*)malloc(sizeof(int));
	//*******************
	// 
	//    *函数体*
	// 假设在执行完后发现空间不够
	// 需要扩容并执行一些操作
	// 
	//*******************

	p = Main_realloc(p,100);  //扩容函数

	free(p);
	p = NULL;
	return 0;
}

The use of pointer functions in some algorithms can greatly reduce the space complexity, but there is one point that needs special attention when using pointer functions:

  • Be sure not to return the address of a local variable or the address of a function parameter, because the local variable will be destroyed directly after the function is used. It is not erased together with the data in the address, but the right to use this part of the memory is returned. So we may get the result we want by chance, but the right to use the data in this part of the memory has been handed back, so it may be reallocated, resulting in being occupied by other data, and we will not get what we want. desired result. It is very likely to cause serious problems such as program crashes due to accessing inaccessible content.
  • But if we have to return the address of a local variable, we must use the static keyword to modify it. static can extend the life cycle of the local variable. For details, please read my previous article ( detailed static keyword )

2. Function pointer

Different from the pointer function, the essence of the function pointer is a pointer, and this pointer points to a function. The definition of the function exists in the code segment, and each function has its own entry address in the code segment, and the function pointer is a pointer to the entry address.

2.1 Definition and use of function pointers

Declaration of function pointer: 函数返回类型 (*标识符) (形参类型1, 形参类型2,···) 如int (*pf)(int, int)
code example:

int test()
{
    
    
	return 0;
}

int main()
{
    
    
 	int (*pTest)(int, int) = &test;
}

In addition, regarding the function pointer, the function name is actually the entry address of the function, similar to the array name. But the function pointer does not have some operations such as addition and subtraction of ordinary pointers, addition and subtraction of integers. Even we use function pointers to call functions without dereferencing.
Code example:


#include <stdio.h>
 
void test1(int a){
    
    
	printf("hello bit\n");
}
 
int main(){
    
    
    //通过typedef关键字将void(*)(int)类型的函数指针重命名为P简化代码
	typedef void(*P)(int a);
  
	//用P的函数指针类型定义一个p指针变量;
	P p = test1; 
	p(1);  
	(*p)(1);//解引用或者不解引用效果相同
	P p1 = &test1;//是否对函数名取地址不影响,无论取不取,函数名代表的都是函数的入口地址
	p1(1);
	return 0;
}

2.2 Application of function pointer

2.2.1 Array of function pointers

An array is a storage space that stores the same type. We have already learned the pointer array; let's recall the definition of the pointer array first, as follows:

int * arr[ 10 ];

Let's put the addresses of n functions into an array, then this array is called a function pointer array, then how should the function pointer array be defined: (as follows)

int (*parr1[10])();   //正确
int *parr2[10]();      //错误
int (*)() parr3[10];   //错误

It is extremely easy to make mistakes when defining an array of function pointers. We must first combine p with [] when defining , indicating that what we define is an array, and the content of the array is int (*)() 类型的函数指针.

Application example: (calculator)
When we don't know the array of function pointers, the code we write may look like this:

#include <stdio.h>
int add(int a, int b)
{
    
    
	return a + b;
}
int sub(int a, int b)
{
    
    
	return a - b;
}
int mul(int a, int b)
{
    
    
	return a*b;
}
int div(int a, int b)
{
    
    
	return a / b;
}
int main()
{
    
    
	int x, y;
	int input = 1;
	int ret = 0;
do
{
    
    
	printf( "*************************\n" );
	printf( " 1:add 2:sub \n" );
	printf( " 3:mul 4:div \n" );
	printf( "*************************\n" );
	printf( "请选择:" );
	scanf( "%d", &input);
	switch (input)
	{
    
    
		case 1:
			printf( "输入操作数:" );
			scanf( "%d %d", &x, &y);
			ret = add(x, y);
			printf( "ret = %d\n", ret);
			break;
		case 2:
			printf( "输入操作数:" );
			scanf( "%d %d", &x, &y);
			ret = sub(x, y);
			printf( "ret = %d\n", ret);
			break;
		case 3:
			printf( "输入操作数:" );
			scanf( "%d %d", &x, &y);
			ret = mul(x, y);
			printf( "ret = %d\n", ret);
			break;
		case 4:
			printf( "输入操作数:" );
			scanf( "%d %d", &x, &y);
			ret = div(x, y);
			printf( "ret = %d\n", ret);
			break;
		case 0:
			printf("退出程序\n");
			breark;
			default:
			printf( "选择错误\n" );
			break;
		}
	} while (input);
	return 0;
}

Then we posted that the code was long and cumbersome, it was not easy to read, and it seemed very redundant. But now we are different now, we have learned the array of function pointers, we should write the following code:

#include <stdio.h>
int add(int a, int b)
{
    
    
	return a + b;
}
int sub(int a, int b)
{
    
    
	return a - b;
}
int mul(int a, int b)
{
    
    
	return a*b;
}
int div(int a, int b)
{
    
    
	return a / b;
}
int main()
{
    
    
	int x, y;
	int input = 1;
	int ret = 0;
	int(*p[5])(int x, int y) = {
    
     0, add, sub, mul, div }; //转移表
	while (input)
	{
    
    
		printf( "*************************\n" );
		printf( " 1:add 2:sub \n" );
		printf( " 3:mul 4:div \n" );
		printf( "*************************\n" );
		printf( "请选择:" );
		scanf( "%d", &input);
		if ((input <= 4 && input >= 1))
		{
    
    
			printf( "输入操作数:" );
			scanf( "%d %d", &x, &y);
			ret = (*p[input])(x, y);
		}
		else
			printf( "输入有误\n" );
		printf( "ret = %d\n", ret);
		}
	return 0;
}

2.2.2 Callback function

A callback function is a function that is called through a function pointer. If you pass a function pointer (address) as a parameter to another function, when this pointer is used to call the function it points to, we say it is a callback function. The callback function is not directly called by the implementer of the function, but is called by another party when a specific event or condition occurs, and is used to respond to the event or condition. For example, the sorting function qsort (which will be explained in a special article in the future) is a typical application of callback functions.

We now use the callback function to implement a sorting function (the way of bubble sorting)

#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{
    
    
	return (*(int*)p1 - *(int*)p2);
}
void _swap(void* p1, void* p2, int size)
{
    
    
	int i = 0;
	for (i = 0; i < size; i++)
	{
    
    
		char tmp = *((char*)p1 + i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}
void bubble(void* base, int count, int size, int(*cmp)(void*, void*))
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < count - 1; i++)
	{
    
    
		for (j = 0; j < count - i - 1; j++)
		{
    
    
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
    
    
				_swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}
int main()
{
    
    
	int arr[] = {
    
     1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
	//char *arr[] = {"aaaa","dddd","cccc","bbbb"};
	int i = 0;
	bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

It is not easy to ask for a three-link, and your support is my biggest motivation.

Guess you like

Origin blog.csdn.net/qq_64293926/article/details/127413545