当前位置:网站首页>[advanced C language] advanced pointer [Part 2]

[advanced C language] advanced pointer [Part 2]

2022-06-10 19:35:00 You and I are all mortals

   author : You and I are all mortals

  Blog home page : You and I are all mortal blogs

  Aphorisms : Time will not stay for anyone , And things and people , It's changing all the time . Every one of us , Also keep moving forward !

  If you think the blogger's article is good , I hope you'll make it three times in a row ( Focus on , give the thumbs-up , Comment on ), Give me more support !!

  series :

 

 C Language programming questions

  Classic question series

 

 

List of articles

Catalog

List of articles

Preface

A function pointer

Function pointer array

A pointer to an array of function pointers

Callback function

Entrance to exercises

  summary


Preface

This chapter not only follows up on the previous chapter, but also explains the new knowledge , About function pointers , Function pointer array , Pointers to function pointer arrays and callback functions are troublesome knowledge points at first glance , Some relatively high knowledge points , I hope you can understand and learn


Tips : The following is the main body of this article , The following cases can be used for reference

A function pointer

The previous array pointer refers to the array pointer

A function pointer is a pointer to a function

So we know that The array pointer is the address of the array , that A function is simply to take the address of the function ?

So let's explore function pointers :

#include<stdio.h>
int add(int x, int y)
{
	return x + y;
}
int main()
{
	int arr[5] = { 0 };
	//& Array name -- The address of the extracted array 
	int(*p)[5] = &arr; // Array pointer 
	//& Function name - What you get is the address of the function ?
	printf("%p\n", &add);
	// Function name , It is the address of the first element of the function , How can a function have a first element ?
	printf("%p\n", add);
	// For functions ,& Function name and function name are the address of the function 
	// If you want to get the address of the function , How to store it ?
	int (*pf)(int, int) = &add;
	return 0;
}

  First of all, pay attention to , Function pointers are actually very similar to array pointers ,& Function name and function name are the address of the function , If you want to get the address of the function , First of all, it is a pointer (*pf) The parameter type in the function is (int,int) The return value is int, This constitutes a function pointer , It points to a function

We use pointers so that we can use them one day , that How function pointers are used

int (*pf)(int, int) = &add;
	int ret = (*pf)(2, 3);
	printf("%d", ret);
	return 0;

  Actually (*pf) Inside * There is no point here , Think about it , since add It can be an address ,&add It's also the address , Then put the add Directly assign to pf It's fine too , Our usual call function is add(2,3), So directly pf(2,3) It's the same thing

So how to use function pointers ?

int add(int x, int y)
{
	return x + y;
}
void calc(int(*pf)(int, int))
{
	int a = 3;
	int b = 5;
	int ret = pf(a, b);
	printf("%d\n", ret);
}
int main()
{
	calc(add);
	return 0;
}

  It seems like a lot of trouble , Call the function directly , Why use it like this ? take it easy , The following will explain an example according to other knowledge points , Let us understand the application scenarios of function pointers

Next, let's look at two interesting and numbing pieces of code :

int main()
{
	 (*(void (*)())0)();
	void (*signal(int, void(*)(int)))(int);
	return 0;
}

  About the drawing and analysis of these two pieces of code :

 

  These two pieces of code adopt c Pitfalls and pitfalls , It is quite difficult to read , If you don't learn this knowledge , So this kind of code certainly doesn't know how to start

Next, let's implement a function pointer , It is convenient for everyone to understand the function pointer

Let's do a simple calculator , The common version is like this :

// The purpose of the function pointer 
// Write a calculator 
// Add , Subtraction , Multiplication , division 

void  memu()
{
	printf("****************************\n");
	printf("**    1 add      2 sub *****\n");
	printf("***   3 mul      4 div *****\n");
	printf("****      0 exit      ******\n");
}
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 input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		memu();
		printf(" Please select :");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf(" Please enter two actual numbers :");
			scanf("%d %d", &x, &y);
			ret = add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf(" Please enter two actual numbers :");
			scanf("%d %d", &x, &y);
			ret = sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf(" Please enter two actual numbers :");
			scanf("%d %d", &x, &y);
			ret = mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf(" Please enter two actual numbers :");
			scanf("%d %d", &x, &y);
			ret = div(x, y);
			printf("%d\n", ret);
			break;
		case 0:
			printf(" Exit calculator \n");
			break;
		default:
			printf(" Wrong choice \n");
			break;
		}
	} while (input);
	return 0;
}

  We found that case1,2,3,4 There is too much code duplication between , Can we directly encapsulate a function , But how to achieve it ?

We make improvements as follows :( Part of the code , Because it's written too much )

We can see below , Function pointer is used , To put all that duplicate code in , The name of every addition, subtraction, multiplication and division function is the address , Then use the function pointer to receive , Call this function internally , This is the callback function , This is not supported without knowing the concept of function pointer

So the function pointer is not a decoration , It is a place that is temporarily unavailable , In fact, it is a clever way

// The purpose of the function pointer 
// Write a calculator 
// Add , Subtraction , Multiplication , division 
// A calculation function encapsulated 
void calc(int (*pf)(int,int))  // A function pointer 
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf(" Please enter two actual numbers :");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}
int main()
{
	int input = 0;
	do
	{
		memu();
		printf(" Please select :");
		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;
		case 0:
			printf(" Exit calculator \n");
			break;
		default:
			printf(" Wrong choice \n");
			break;
		}
	} while (input);
	return 0;
}

Function pointer array

An array is a storage space for the same type of data , We have learned about multiple arrays , such as :

int* arr【5】

char* arr【6】

int  arr【4】

So a function pointer is a pointer , Put functions and pointers into arrays , It is actually an array of function pointers

The following code explains the function pointer 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 (*pf)(int, int) = add;//pf It's a function pointer 
	// imitation 
	int (*arr[4])(int, int) = { add,sub,mul,div };
}

  So how do we understand ? Drawing comprehension :

  How to use it ? We can use the traversal method :

int main()
{
	int (*pf)(int, int) = add;//pf It's a function pointer 
	// imitation 
	int (*arr[4])(int, int) = { add,sub,mul,div };
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		int ret = arr[i](8, 4);
		printf("%d\n", ret);
	}
}

  You may have some doubts here , What's the use ? Don't worry , Let's look at a set of code applications , Or the calculator above , So let's revise that :

// The purpose of the function pointer 
// Write a calculator 
// Add , Subtraction , Multiplication , division 
// Transfer table 
void  memu()
{
	printf("****************************\n");
	printf("**    1 add      2 sub *****\n");
	printf("***   3 mul      4 div *****\n");
	printf("****      0 exit      ******\n");
}
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 input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	// An array of function pointers 
	int(*pfarr[5])(int, int) = { 0,add,sub,mul,div };
	do
	{
		memu();
		printf(" Please select :");
		scanf("%d", &input);
		pfarr[input];// Get the element with subscript number according to the entered number 
		if (input == 0)
		{
			printf(" Exit calculator \n");
			
		}
		else if (input >= 1 && input <= 4)
		{
			printf(" Please enter two actual numbers :");
			scanf("%d %d", &x, &y);
			ret = pfarr[input](x, y);
			printf("%d\n", ret);
		}
		else
		{
			printf(" Wrong choice \n");
		}
	} while (input);
	return 0;
}

  In the code above , We used an array of function pointers , Make the code very concise , Even if our calculator wants to go into some functions , Add some features , It also becomes very simple

A pointer to an array of function pointers

The pointer to the array of function pointers is a pointer

The pointer points to an array , The elements of the array are function pointers

How to define ? As shown below :( Understanding can , It doesn't go deep here )

#include<stdio.h>
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;
}
#include<stdio.h>
int main()
{
	// Function pointer array 
	int (*pfarr[])(int, int) = { 0,add,sub,mul,div };
	// A pointer to an array of function pointers 
	int (*(*ppfarr)[])(int,int) = &pfarr;
	return 0;
}

Callback function

A callback function is a function called through a function pointer . If you put a pointer to a function ( Address ) Pass as argument to another function , When this pointer is used to call the function it points to , Let's just say this is a callback function . The callback function is not called directly by the function's implementer , It's called by another party when a particular event or condition occurs , Used to respond to the event or condition .
I know it seems hard to understand , Never mind , Let's use an example to explain
First of all, we have been exposed to bubble sorting before , Know that bubbling sort can only run in shaping , Can only be sorted for integer , Let's sort and library functions according to bubbles qsort To explain :
Initial edition ( Only integer data can be sorted ):
#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int flag = 1;// Suppose the array is ordered 
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	// Generate the array in ascending order 
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

Next, let's show qsort Use of functions ( The second version ):

 ( Use qsort Implement sort integer )( Equivalent to callback function )

// Compare two integer elements 
//e1 Point to another integer 
//e2 Point to another integer 
#include<stdio.h>
#include<string.h>
int cmp_int(const void* e1, const void* e2)//void* Is a pointer without a specific type , Can accept any type of address 
// Therefore, you cannot dereference the operation , Also can not +- Integers 
{
	return (*(int*)e1) - (*(int*)e2);
}
void test1()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	// Generate the array in ascending order 
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
struct stu
{
	char name[20];
	int age;
};
int cmp_stu(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
void test2()
{
	// Test use qsort To sort structural data 
	struct stu s[] = { {"zhangsan",15},{"lisi",59},{"liwa",44} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu);
	// Debug view memory 
}
int main()
{
	test1();
	test2();
	return 0;
}

Next, transform the first bubble sort ( simulation qsort function )

#include<stdio.h>
void swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1) - (*(int*)e2);
}
void bubblu_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		int flag = 1;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				// In exchange for 
				swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	// Generate the array in ascending order 
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubblu_sort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

Entrance to exercises

After reading these specific operations, it is not allowed , You can click on the top to practice some exercises , You can also have a casual look C Some language exercises , Practice multiple-choice questions and programming questions , Let your knowledge be consolidated , Click directly into the title to go directly to , In addition, if you want to get the qualification of internal promotion of large factories, you can also go and have a look :

Large factory push

It is highly recommended that you practice the exercises here , Friendly to novices , The topics are from the simplest aspects , You can choose a series of difficulties, such as simple introduction and medium difficulty , I practiced for a long time , Let's go on the journey of question brushing :

Niuke website practice direct

 

 

  summary


This chapter not only follows up on the previous chapter, but also explains the new knowledge , About function pointers , Function pointer array , Pointers to function pointer arrays and callback functions are troublesome knowledge points at first glance , Some higher knowledge points give different examples to let you know the application of these knowledge , It also explains what the transfer table is and the library functions qsort Simulation Implementation of , Step by step , If you think the blogger's explanation is good , I hope you can support me more , Thank you for watching

原网站

版权声明
本文为[You and I are all mortals]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/161/202206101827265666.html