C language: the second layer of pointer (Advanced)

Posted by Garethp on Sat, 15 Jan 2022 04:11:22 +0100

catalogue

1. Character pointer

 2. Pointer array

3. Array pointer

4. Array parameters and pointer parameters

5. Function pointer

6. Function pointer array

7. Pointer to function pointer array

8. Callback function

When we first learned the C language, we had a preliminary contact with the existence of pointer and had a general understanding of pointer

        1. The pointer is a variable, which is used to store the memory address. The address in the memory uniquely identifies a piece of memory space!

        2. The size of the pointer is fixed at 4 / 8 bytes (32-bit system platform / 64 bit system platform)

        3. Pointers have specific types. The type of pointer determines the step size (or span) offset by the pointer when it is a + / - integer, and how many bytes of permission to access when the pointer is dereferenced

        4. Can be used for pointer operations

In this article, continue to explore new pointers to deeper topics

1. Character pointer

After first knowing the pointer, we all know that there is a type of pointer called character pointer - char *;

For general use of pointers:

int main()
{
	char ch = 'W';//Create char variable ch
	char* pc = &ch; //Take out the memory address of the variable ch and put it into the character pointer variable pc. the content of pc is the address of ch
	*pc = 'A';//Find ch by pointer dereference and modify its content value
	return 0;
}

There is another use of character pointers:

int mian()
{
	char* pc = "hello word";//A thought, is this putting a string into the pc pointer?
	printf("%s\n", pc);
	return 0;
}

In the second code block, char* pc = "hello word"; It is very easy to make people think that a string hello word is put into the character pointer pc, but in fact, this code essentially only puts the address of the first character of hello word {h} into the pc

Let's look at an interesting topic

#include <stdio.h>
int main()
{
	char str1[] = "hello word";
	char str2[] = "hello word";
	char* str3 = "hello word";
	char* str4 = "hello word";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

At the first sight, everyone will think that the output result is str1 and str2 are same /str3 and str4 are not same, but in fact, the result is quite the opposite!! Let's see the results first

The final output here is:

Many people should be surprised why str1 and str2 are not equal?

In fact, it is very simple. str1 and str2 are arrays, and the strings stored in the array are the same, but you should not forget that the array name represents the address of the first element of the array. Since they are two arrays, they must have two different spaces. Although the stored contents are the same, their addresses are completely different. The following judgment statement is whether the addresses are equal to each other, Obviously, the output must be else

If so, why is str3 equal to str4? Because str3 and str4 as like as two peas, they are not arrays, they are pointer variables, but only point to the same string hello word. This string is a constant string, the character of constant string: it can be accessed, it can be used, but it can not be modified. So, since it is not modifiable, there is no need to store two identical string in the memory. Then str3 and str4 store the address of h in this constant string. After the if statement determines that the output result is the same~

 2. Pointer array

In the preliminary understanding of pointers, I also learned about pointer array. Pointer array is essentially an array used to store multiple pointer sets of the same type

	int* arr1[10]; //Array of integer pointers
	char* arr2[4]; //Array of first level character pointers
	char** arr3[5];//Array of secondary character pointers

Pointer array is very simple to use:

int main()
{
	//int* arr1[10]; // Array of integer pointers
	//char* arr2[4]; // Array of first level character pointers
	//char** arr3[5];// Array of secondary character pointers
	//Create three arrays
	int a[] = { 1,2,3,4,5 };
	int b[] = { 6,7,8,9,10 };
	int c[] = { 11,12,13,14,15 };
	//Create a pointer array and save the pointers into three arrays
	int* tmp[3] = { a,b,c };
	//Use the pointer array to print the spatial content pointed to by the three pointers
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", * (tmp[i] + j));//Writing method 1;
			//printf("%d ", *(*(tmp + i) + j));// Writing method 2;
			//printf("%d ", tmp[i][j]);// Writing method 3;

		}
		printf("\n");
	}
	return 0;
}

In this code, I create three int type arrays and store five elements each

Then, a pointer array is created to store the pointers of the three arrays. As we all know in the previous study, the array name represents the address of the first element. Since it represents the address of the first element, it is an address. In fact, the address is a pointer, which can be understood as that the array name is actually a level-1 pointer. When creating a pointer array, tmp is combined with [] first, It means that it is an array. There are three elements in the array. The type of each element is int * which is enough to prove that it is a pointer array. Then put the array names of the three arrays into it. In fact, it stores three first-order pointers

In the following printing, printf actually has three writing methods. In the first writing method, tmp[i] is actually equivalent to * (tmp+i) getting the space pointed to by a pointer in the tmp array, and then + j dereference outside, that is, getting the element at that position and printing it, which is equivalent to writing method 2: * (* (tmp+i) + j writing method 2 is equivalent to writing method 3:tmp[i][j]

3. Array pointer

3.1 definition of array pointer

Is an array pointer a pointer? Or an array?

The answer is: pointer

We are already familiar with:

Integer pointer: int * pint; A pointer that can point to shaped data.

Floating point pointer: float * pf; A pointer that can point to floating point data.

The array pointer should be: a pointer that can point to an array.

Which of the following code is an array pointer?

int *p1[10];
int (*p2)[10];
//What are P1 and P2?

Explanation:

int *p1[10]; Among the priorities we have learned, the priority of [] is higher than * so P1 is combined with [] first. At this time, P1 is an array with 10 elements. The type of each element is int *, so it is a pointer array!

int (*p)[10] ; Here () has the highest priority, so p is combined with * first. At this time, P is a pointer, and int [10] remains after P is removed; Prove that the pointer points to an array. The array has 10 elements, and each element is of type int;  

//Note here that the priority of [] is higher than * so () must be added to ensure that p is combined with * first

3.2 & array name VS array name

For the following array:

int arr[10];

What are arr and & arr?

Where arr is the array name, and the array name represents the address of the first element

What is the &arr array name? Look at a piece of code:

#include <stdio.h>
int main()
{
    int arr[10] = {0};
    printf("%p\n", arr);
    printf("%p\n", &arr);
    return 0; 
}

The operation results are as follows:

It can be seen that the address printed by the array name and & array name is the same.

Are the two the same?

Let's look at another piece of code:

#include <stdio.h>
int main()
{
 int arr[10] = { 0 };
 printf("arr = %p\n", arr);
 printf("&arr= %p\n", &arr);
 printf("arr+1 = %p\n", arr+1);
 printf("&arr+1= %p\n", &arr+1);
 return 0; 
}

Its running results are as follows

According to the above code, we find that although the values of & arr and arr are the same, they should have different meanings.

In fact: & arr represents the address of the array, not the address of the first element of the array.

The address of the array is + 1, skipping the size of the entire array, so the difference between & arr + 1 and & arr is 40

3.3 use of array pointer

How are array pointers used?

Since the array pointer points to an array, the address of the array should be stored in the array pointer.

Look at the code:

#include <stdio.h>
int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,0};
    int (*p)[10] = &arr;//Assign the address of array arr to array pointer variable p
    //But we rarely write code like this
    return 0; 
}

Why do I say that I seldom write code like this? Because array pointers are not so appropriate for one-dimensional arrays. The most suitable pointer for one-dimensional arrays is the first-order pointer, not the array pointer. If you don't believe it, look at the printing of one-dimensional arrays by array pointers in the following code:

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int(*p)[10] = &arr;//Assign the address of array arr to array pointer variable p
	int* a = arr; //Pay the address of the first element of the array to the first level integer pointer a;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *((*p) + i));//Array pointer how to print a one-dimensional array
		printf("%d ", *(a + i));//How to print one-dimensional array with one-level pointer
	}

	return 0;
}

In this code, it is obvious that the one-dimensional array printing with the first level pointer will be better both in writing and readability. It is also possible to use the array pointer, but it seems a little chicken killing. Generally, the array pointer is used for the two-dimensional array

Use of an array pointer:

#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col) {
    int i = 0;
    for(i=0; i<row; i++)
   {
        for(j=0; j<col; j++)
       {
            printf("%d ", arr[i][j]);
       }
        printf("\n");
   }
}
void print_arr2(int (*arr2)[5], int row, int col) {
    int i = 0;
    for(i=0; i<row; i++)
   {
        for(j=0; j<col; j++)
       {
            printf("%d ", arr2[i][j]);
       }
        printf("\n");
   }
}
int main()
{
    int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
   print_arr1(arr, 3, 5);
    //The array name arr represents the address of the first element
    //But the first element of the two-dimensional array is the first row of the two-dimensional array
    //So the arr passed here is actually equivalent to the address of the first row, which is the address of a one-dimensional array
    //You can use array pointers to receive
    print_arr2(arr, 3, 5);
    return 0; 
}

Explanation:

In the arr1 function, there must be no problem using a two-dimensional array to transfer parameters and receive parameters. There is no need to explain this too much

The focus is on arr2, two-dimensional array parameter transmission and pointer array reception, In fact, the two-dimensional array of arr can be regarded as three elements. The type of each element is a one-dimensional array. Each one-dimensional array has five elements. Each element is of type int. then the address of the first element of arr is the address of the first one-dimensional array. At this time, it is more appropriate to use the array pointer to receive, but the array pointer variable skips a one-dimensional array every + 1, Because in arr, these three one-dimensional arrays are stored continuously! You can see the figure below for further understanding

 

After learning pointer array and array pointer, let's review and see the meaning of the following code:

int arr[5]; //arr is first combined with [], so it is an array with 5 elements, and each element is of type int;
int *parr1[10];//parr1 and [] first, so it is an array with 10 elements, and each element is of type int *;
int (*parr2)[10];//parr2 is first combined with * so it is a pointer. After removing the name, int[10] is left; Prove that the pointer points to an array of 10 elements, each of which is of type int;
int (*parr3[10])[5];//parr3 is first combined with [], which is an array with 10 elements. After removing the combined, int(*)[5] is left, which proves that each element is an array pointer;

4. Array parameters and pointer parameters

When writing code, it is inevitable to pass [array] or [pointer] to the function. How to design the parameters of the function?

4.1 one dimensional array parameter transfer

#include <stdio.h>
void test(int arr[])//ok?  -ok
{} //This is certainly no problem. One dimensional array passes parameters, and formal parameters are received with one-dimensional array
void test(int arr[10])//ok? --ok
{}/*This is no problem, but there are 10 more formal parameters in [] than the above, but it won't really create 10 more element spaces ~ so this
10 It's just a decoration*/
void test(int *arr)//ok? --ok
{}/*The array name represents the address of the first element. As long as it is the address of the first element of a one-dimensional array, it is a level-1 pointer, so it is received with a level-1 pointer
 It's OK*/
void test2(int *arr[20])//ok?  --ok
{} /*Array parameters are received by arrays of the same type, and the appropriate ones cannot be more appropriate*/
void test2(int **arr)//ok?
{}/*The array name represents the address of the first element. If the element type of the array is int *, the address of the first element of the array must be a secondary pointer
 So OK*/
int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0};
 test(arr);
 test2(arr2);
}

4.2 two dimensional array parameter transfer

void test(int arr[3][5])//ok? --ok
{}//Array pass parameter group receive OK~
void test(int arr[][])//ok?  --err
{}//Two dimensional array can only omit rows, not columns! Including transmission parameters
void test(int arr[][5])//ok?  --ok
{}//Rows can be omitted and columns cannot be omitted. This is ok
//Summary: for the design of two-dimensional array parameters and function parameters, only the first [] number can be omitted.
//Because for a two-dimensional array, you can't know how many rows there are, but you must know how many elements there are in a row.
//This is convenient for calculation.
void test(int *arr)//ok?  --err
{}//This certainly won't work. The address of the first element of a two-dimensional array is the array pointer type. How can I receive it with a one-dimensional array!
void test(int* arr[5])//ok?  --err
{}//This is a first-order pointer array. It is not of the right type, and it is impossible to receive
void test(int (*arr)[5])//ok?  --ok
{}//The address of the first element of a two-dimensional array is the array pointer type, which can be received and used
void test(int **arr)//ok?  --err
{}//Array pointers cannot be received with a two-dimensional array
int main()
{
 int arr[3][5] = {0};
 test(arr);
}

4.3 primary pointer transfer parameter

#include <stdio.h>
void print(int *p, int sz) {
 int i = 0;
 for(i=0; i<sz; i++)
 {
 printf("%d\n", *(p+i));
 }
}
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9};
 int *p = arr;
 int sz = sizeof(arr)/sizeof(arr[0]);
 //First level pointer p, passed to function
 print(p, sz); //Here, the first level pointer only passes parameters, not values. The content stored in the first level pointer is an address, so the function parameters are received with the first level pointer
 return 0; 
}
reflection:
When the parameter part of a function is a first-order pointer, what parameters can the function receive?

For example:

void test1(int *p)
{}
//What parameters can the test1 function accept?
//Answer: & int type variable, int type first-order pointer to pass parameters, int type one-dimensional array to pass parameters,
void test2(char* p)
{}
//What parameters can the test2 function accept?
//Answer: & char type variable, char type first-order pointer to pass parameters, char type one-dimensional array to pass parameters,

Similarly, two-level pointer, three-level pointer, four-level pointer, etc. ~ you can think more about these according to the above examples

5. Function pointer

Let's start with a code:

#include <stdio.h>
void test()
{
 printf("hehe\n");
}
int main()
{
 printf("%p\n", test);
 printf("%p\n", &test);
 return 0; 
}

The output of this code is:

It is sufficient to prove that the function name and the & function name are equal

Here is a knowledge point: array name ≠ & array name, but function name = & function name. The function does not have the so-called first element address, so the function name is the address. Taking the address, the function name and the function name are equivalent

Since the function name is the function address, it can also be put into the pointer. Such a pointer is called the pointer to the function, or function pointer for short

Creation of function pointer:

#include <stdio.h>
void test(int a,int b)
{
	printf("hehe\n");
}
int main()
{
	void (*pf) (int, int) = test; //Or write = & test;
	//(* pf) combine first, which means it is a pointer. Remove the combined, and leave void (int,int) as a function
	//Prove that the pointer points to a function. The parameter type of this function is int and the return type of int is void
	return 0;
}

Call of function pointer:

#include <stdio.h>
void test(int a,int b)
{
	printf("hehe\n");
}
int main()
{
	void (*pf) (int, int) = test; 
	(*pf)(3, 5);//Writing method 1 is equivalent to test(3,5), so since the two are equivalent to each other, there is a second writing method
	pf(3, 5);//In writing 2, the dereference symbol in writing 1 is actually a decoration. pf and test are equivalent to each other. Test is called by using pf, so there is no need to add dereference
	//Wrong writing method: * pf(3,5) must not be written like this. If it is written like this, call the function first
	//Then dereference the return value of the function. This is the wrong way to write!!!
	return 0;
}

Note that the * dereference operator can be omitted only when the function pointer is used!

6. Function pointer array

Since functions can be stored in pointers, function pointers can naturally be placed in an array of function pointers

Function pointer array creation:

//  Type (* array name [number]) (function parameter.....)= {function name (or function pointer), function name (or function pointer), function name (or function pointer);
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 (*pff[4])(int, int) = { add,sub,mul,div };//Creation of function pointer array
	//Analysis: pff is combined with [4] first. It is an array with 4 elements
	//After removing the combined elements, there are int (*) (int, int), four elements, each of which is a function pointer
	//Each function pointer points to a function. The return type of each function is int, and the parameter type is int,int
	return 0;
}

Use of function pointer array (calculator):

First use the learned knowledge to create the calculator, and then use the function pointer array to transform it on the basis of

void menu()
{
	printf("*******************************\n");
	printf("********1.add     2.sub********\n");
	printf("********3.mul     4.div********\n");
	printf("*********** 0.exit ************\n");
	printf("*******************************\n");
}
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 input = 0;//option
	do
	{
		menu();//Print menu
		printf("Please select an option:>");
		scanf("%d", &input);
		int a = 0;//Number of calculations 1
		int b = 0;//Calculation number 2
		int ret = 0;//Receive return value
		switch (input)
		{
		case 1:
			printf("Please enter two operands:");
			scanf("%d %d", &a, &b);
			ret = add(a, b);
			printf("%d\n", ret);
			break;
		case 2:
			printf("Please enter two operands:");
			scanf("%d %d", &a, &b);
			ret = sub(a, b);
			printf("%d\n", ret);
			break;
		case 3:
			printf("Please enter two operands:");
			scanf("%d %d", &a, &b);
			ret = mul(a, b);
			printf("%d\n", ret);
			break;
		case 4:
			printf("Please enter two operands:");
			scanf("%d %d", &a, &b);
			ret = div(a, b);
			printf("%d\n", ret);
			break;
		case 0:
			printf("Exit program!");
			break;
		default:
			printf("Incorrect input,Please re-enter\n");
			break;
		}


	} while (input);
	return 0;
}

Although this code is readable, most of the code for each option in its switch is repetitive, which is very redundant. If this calculator needs to add more functions, its branches need more repetitive code, which is not a good thing for maintenance

How to write a function pointer array:

void menu()
{
	printf("*******************************\n");
	printf("********1.add     2.sub********\n");
	printf("********3.mul     4.div********\n");
	printf("*********** 0.exit ************\n");
	printf("*******************************\n");
}
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 input = 0;//option
	do
	{
		menu();//Print menu
		printf("Please select an option:>");
		scanf("%d", &input);
		int a = 0;//Number of calculations 1
		int b = 0;//Calculation number 2
		int ret = 0;//Receive return value
		int (*ppf[5])(int, int) = { NULL,add,sub,mul,div };//The first element is NULL so that options and corresponding functions can be used directly
		if ((input <= 4 && input >= 1))//Function determination area
		{
			printf("Please enter two operands:");
			scanf("%d %d", &a, &b);
			ret = ppf[input](a, b);//Equivalent to ret = (*(ppf+input)) (a,b);
			printf("%d\n", ret);
		}
		else if (input == 0)
		{
			printf("Exit program\n");
		}
		else
		{
			printf("Incorrect input,Please re-enter\n");
		}
	} while (input);
	return 0;
}

In this code, several functions are connected in series by using the function pointer array, and the calculation is carried out directly by calling the parameters, which saves a lot of repeated and redundant code. For the future, if you want to add new functions or modify and maintain, there is less code to be rewritten, Just add or delete the corresponding function and modify the value of the function determination area and the number of functions in the array. This use method also has another name: transfer table;

7. Pointer to function pointer array

The pointer to the array of function pointers is a pointer
The pointer points to an array whose elements are function pointers
To define a pointer to a function pointer array:
void test(const char* str) {
 printf("%s\n", str);
}
int main()
{
 //Function pointer pfun
 void (*pfun)(const char*) = test;
 //Array of function pointers pfunArr
 void (*pfunArr[5])(const char* str);
 pfunArr[0] = test;
 //Pointer to function pointer array pfunArr ppfunArr
 void (*(*ppfunArr)[10])(const char*) = &pfunArr;
//ppfunArr first combines with * to prove that it is a pointer, which points to an array and 10 elements
//Each element of the array is a function pointer type, so it is a pointer to the array of function pointers
 return 0; 
}

At present, we'd better understand it first. We'll practice it slowly in the later stage. Everyone should feel like Russian dolls, layer by layer, endless, which will test the logic of everyone's thinking

8. Callback function

A callback function is a function called through a function pointer. If you pass the pointer (address) of a function 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 created by the
The implementer of a function is called directly, but by another party when a specific event or condition occurs, which is used to
Respond to conditions.
To put it simply: a pointer to one function 1 is called and returned by function 2 as a parameter of another function 2 to use function 1. Responding to the call of function 2 is called a callback function;

Use of callback function:

Take the calculator just now as an example

void menu()//Callback function writing
{
	printf("*******************************\n");
	printf("********1.add     2.sub********\n");
	printf("********3.mul     4.div********\n");
	printf("*********** 0.exit ************\n");
	printf("*******************************\n");
}
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 Cofe(int (*pf)(int, int))
{
	int a = 0;//Number of calculations 1
	int b = 0;//Calculation number 2
	printf("Please enter two operands:");
	scanf("%d %d", &a, &b);
	return pf(a, b);
}
int main()
{
	int input = 0;//option
	do
	{
		menu();//Print menu
		printf("Please select an option:>");
		scanf("%d", &input);
		int ret = 0;//Receive return value
		switch (input)
		{
		case 1:
			ret = Cofe(add); 
			printf("%d\n", ret);
			break;
		case 2:
			ret = Cofe(sub);
			printf("%d\n", ret);
			break;
		case 3:
			ret = Cofe(mul);
			printf("%d\n", ret);
			break;
		case 4:
			ret = Cofe(div);
			printf("%d\n", ret);
			break;
		case 0:
			printf("Exit program!");
			break;
		default:
			printf("Incorrect input,Please re-enter\n");
			break;
		}


	} while (input);
	return 0;
}

The difference between this code and the previous code is that I encapsulate the redundant code with a function whose parameter is a function pointer type. Then we transfer the parameters of the corresponding code block function function, input the operands in the Cofe function, calculate and return the results with ret, and each case is only responsible for receiving the results and printing them, The callback function mechanism is used to call other functions for calculation through the function Cofe, and the return value makes a reply to the call of Cofe function, which is the callback function

Take the library function qsort as an example and imitate the qsort function:

qsort: quick sort is a function in the library function, which can quickly sort arrays of any type

(all the sorting methods we wrote before have to pick the type, but qsort does not pick the type. It can sort whatever type array it is given.)

qsort function declaration:

void qsort (void* base, size_t num, size_t size,
            int (*compar)(const void*,const void*));

You can see that qsort has four parameters, where void* base represents the starting address of the array to be sorted, and size_t num is the number of elements in the array to be sorted, size_t size is to sort the size (bytes) of the elements in the array, and the last function pointer is the essence of the qsort function. This function pointer is a function created and supplied by qsort users, which is used for quick sort (ascending / descending) of qsort (if the value returned is >0, ascending <0 is descending).

Use of qsort

#include <stdlib.h>
#include <stdio.h>

int cmp(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;//This is the operator's forced type conversion according to the array type to be sorted
	//Because the void * type is a pointer without a specific type, it does not know how many bytes it will access
	//Dereference of void * type directly will report an error: illegal indirect addressing
	//void * is like a garbage can. It can receive any type of pointer you give it
}
void print(int* p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	printf("\n");
}

int main()//qsort quick sort
{
	int arr[] = { 4,6,8,0,1,3,5,2,9 };//Create array
	int sz = sizeof(arr) / sizeof(arr[0]);//Number of array elements
	print(arr, sz);//Prints the array before it is not sorted
	qsort(arr, sz, sizeof(arr[0]), cmp);
	print(arr, sz);//Print the sorted array
}

The output of this program is:

 

Imitate qsort to realize a simple and general bubble sorting (ascending order):

int cmp(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

void Swap(char* e1, char* e2, int width)
//There are three parameters in this function, e1 represents the starting address of exchange element 1, e2 represents the starting address of exchange element 2, and width is the size of the two elements
//The pointer is set to char * so that more types of elements can be merged
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *e1;
		*e1 = *e2;
		*e2 = tmp;
		e1++;
		e2++;
		//For various types of elements, this loop sequentially exchanges each byte in each type of element, and char * accesses only one byte at a time
		//width indicates how many bytes these elements are, and only how many bytes need to be exchanged, which is used to limit the function
	}

}

void my_qsort(void* base, int sz, int width, int(*pf)(const void* e1, const void* e2))
{
	int i = 0;
	//Number of trips
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;\
		//Sorting of each trip
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0) //Since void * is a pointer without a specific type, it is cast to a char * type pointer
			//The char * type pointer can access one byte at a time. At this time, we can use the width we passed to the size of each element of the array
			//Then call cmp for the addresses of + j*width and + (j+1)*width to calculate and return the judgment. The callback function mechanism is used here
			//Exchange if satisfied
			{
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);//Exchange function
			}

		}
	}
}
void print(int* p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	printf("\n");
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };//Create array
	int sz = sizeof(arr) / sizeof(arr[0]);//Number of array elements
	print(arr, sz);//Prints the array before it is not sorted
	my_qsort(arr, sz, sizeof(arr[0]), cmp);
	print(arr, sz);//Print the sorted array
	return 0;
}

The output of the program is: 

 

The above is all the contents of pointer advanced. Thank you for watching ~ I hope you can have a deeper understanding of pointer from me

Topics: C Back-end