Retrospective Pointer
1,A pointer is a variable that stores an address that uniquely identifies a block of memory space. 2.Pointer size is fixed 4 / 8 Bytes (32-bit platform) / 64 Bit Platform). 3.Pointer is of type, the type of pointer determines the type of pointer +- The step size of an integer, the permissions for pointer dereferencing (accessing several bytes at a time) 4.Operation of Pointer
Take an example to recall
#include<stdio.h> void test(int* arr)// Here arr is a copy of the address of the first element of the array { printf("%d\n",sizeof(arr[0]));// One element size of the calculated array, output 4 printf("%d\n",sizeof(arr));// The size of the address is calculated (not an array address here, because it is a copy of the address of the first element passed in from test), and the output is 4 // 32-bit system sizeof(arr)Here is the pointer(address)Size (4) byte) sizeof(arr[0])What you're looking for here is the size of an element. int Type (4 bytes) If it is a 64-bit system. The pointer size is 8 bytes, and the output is 2 } int main() { int arr[10] = { 0 }; test(arr);//Passed over is the address of the array header element because it is not used alone with the sizeof and & operators return 0; }
1. Character pointer
In the type of pointer we know that there is a pointer type called character pointer char*·
Procedure 1:
#include<stdio.h> int main() { char ch = 'w'; char* pc = &ch; *pc =='w'; return 0; }
Procedure 2:
#include<stdio.h> int main() { char arr[] = "abcdef"; char* pc = arr;//The address of the first element a is stored here printf("%s\n",arr);//abcdef printf("%s\n",pc);//abcdef Prints both backwards until it stops at'\0' %s Just start printing backwards based on the given address location, knowing you have encountered'\0'Stop it return 0; }
Procedure 3:
#include<stdio.h> int main() { char* p = "abcdef";// abcdefAbcdef\0,, caused by the double quotation mark "abcdef", is a constant string // The expression above means that the address of a is stored in the pointer variable p printf("%c\n",*p);// *p == a // Output as a printf("%s\n",p);//Print back until you encounter'\0'starting at the address where you put p (the address of the first element a) // That is, the output is abcdef return 0; }
Procedure 4:
#include<stdio.h> int main() { const char* p = "abcdef";// The safest way to write is to precede * with const *p = 'w';// You can't change it at this point, and "abcdef" is a constant string. printf("%s\n", p); //You will find that there is no output and the program crashes. //Another reason is that abcdef0 is a constant string and cannot be altered (const: a variable has a constant attribute) return 0; }
Procedure 5:
#include<stdio.h> int main() { char arr1[] = "abcdef"; char arr2[] = "abcdef"; if (arr1 == arr2)//Here is the name of the array of two different arrays (different first element addresses) and if they are the same //Definitely different, the starting space of two different arrays must be different { printf("hehe\n"); } else { printf("haha\n");// So output this statement } return 0; }
Procedure 6:
#include<stdio.h> int main() { It is recommended that the following two expressions be used in * Front Epidemic Prevention const ,This makes it safer to modify the contents of a constant string by dereferencing This way, although not significant (the constant string itself cannot be modified), the syntax is more accurate const char* p1 = "abcdef"; const char* p2 = "abcdef"; Here we put the constant string abcdef\0 The first element ( a)Addresses are stored in two pointer variables Because abcdef\0 Is a constant string and cannot be changed, so there is no need to create two and share one directly, that is p1 == p2 if (p1 == p2) { printf("hehe\n");// So output this statement } else { printf("haha\n"); } return 0; }
Pointer array - essentially an array
stay pointer In this article, we also learned about pointer arrays, which are arrays that hold pointers.
Procedure 1:
#include<stdio.h> int main() { int arr[10] = { 0 };// Integer array char ch[5] = { 0 };// Character Array int* parr[4];// This is an array of integer pointers, or simply an array of pointers char* pch[5];// This is an array of character pointers, or simply an array of pointers return 0; }
Procedure 2:
#include<stdio.h> int main() { int a = 10; int b = 20; int c = 30; int d = 40; int* arr[4] = { &a, &b, &c, &d }; Equivalent to //int* pa = &a; //int* pb = &b; //int* pc = &c; //int* pd = &d; int i = 0; for (i = 0; i < 4; i++) { printf("%d ",*arr[i]);// 10 20 30 40 } return 0; // Pointer arrays are rarely used. The following program will tell you how to use them }
Procedure 3:
#include<stdio.h> int main() { int arr1[] = { 1, 2, 3, 4, 5 }; int arr2[] = { 2, 3, 4, 5, 6 }; int arr3[] = { 3, 4, 5, 6, 7 };//The above three expressions mean that I have three arrays and the content is... int* parr[] = { arr1, arr2, arr3 }; // Save the array name/address of the first element of the three arrays above into this pointer array int i = 0; for (i = 0; i < 3; i++)// Traversing elements of pointer array parr { int j = 0; for (j = 0; j < 5; j++)// Traversing through the elements of the pointer array parr points to the elements of the array { printf("%d ",*(parr[i] + j)); } printf("\n"); } return 0; }
Here we review the secondary pointer
int* arr1[]; //Primary integer pointer array.
int** arr[]; //Secondary integer pointer array
ichar* arr2[]; //Primary Character Pointer Array
char** arr2[]; //secondary character pointer array
Array Pointer-Pointer
Procedure 1:
#include<stdio.h> int main() { int* p = NULL;// Plastic Pointer - Pointing to Plastic Pointer Effect: Address where the Plastic can be stored char* pc = NULL;//Character Pointer - Pointing to Characters: Addresses where characters can be stored Array Pointer - Pointer to Array: Address where the array can be stored //Int arr[10] = {0}; integer array // arr - First element address // &arr[0] - Address of the first element // &arr - Address of the array int arr[10] = {1,2,3,4,5,6,7,8,9,10}; int(* p)[10] = &arr;// Save the address of the array // Why can't you remove (), because [] has a higher priority than *, remove (), p is combined with the array [10] and becomes an array of pointers (the array that holds the pointers) // Plus () combines * with P first, making p a pointer (note also that this is not a dereference, just a pointer) // Remove *p, leaving int [10], meaning that the pointer (p) points to an array of 10 elements, each of which is of type integer // That is, the expression int(*p)[10] above is an array pointer return 0; }
Procedure 2:
#include<stdio.h> int main() { char* arr[5]; //How do I save an array of the above expressions into an array pointer? as follows char*(*pa)[5]=&arr; // First use () to combine * with PA so that PA is a pointer, that is * tells us pa is a pointer //Then add [5], meaning the pointer points to an array of five elements // Also, because the element type of the array pointed to by the pointer is char*, add int arr2[10] = { 0 }; int (*pa2)[10] = &arr2; return 0; }
&Array name VS array name
Array names are mostly first element addresses There are only two exceptions &Array name and sizeof(Array name) In both cases, the array name, representing the entire array, takes out the address of the array (same as the address of the first element of the array, but with different meaning)
For instance
&arr+1 - Skip bytes of an entire array directly
For example, int arr[10], whose size is 40 bytes, &arr+1 array address adds 40
If it's arr+1 it skips only one element, meaning it skips the first element and the address points to the second element
Usage of array pointers: commonly used in two-dimensional arrays
Procedure 1:
#include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10}; int (*pa)[10] = &arr; int i = 0; for (i = 0; i < 10; i++) { //Printf ("%d", (*pa)[i]); //*PA equals array name*pa == arr printf("%d ",* (*pa+i) );//Equivalent to printf ('%d', *(arr+i)) } return 0; // But array pointers don't work that way, they just give you a deeper understanding of them }
Before we know what array pointers really do, we need to look at a program
#include<stdio.h> int main() { int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int i = 0; int* p = arr;// The pointer variable p receives the address of the first element of the array, that is, p == arr for (i = 0; i < 10;i++) { printf("%d ",*(p+i));// Traverse through array elements by the address of the first element of the array } printf("\n"); Both upper and lower loops express large amounts of the same effect for (i = 0; i < 10; i++) { printf("%d ", *(arr + i)); } printf("\n"); for (i = 0; i < 10; i++) { printf("%d ", arr[i]);// arr[i] == *(arr+i) == *(p+i) == p[i] } printf("\n"); Both upper and lower loops express large amounts of the same effect for (i = 0; i < 10; i++) { printf("%d ", p[i]);// arr[i] == p[i] } //All of the above are equivalent. return 0; }
Program 2 (use of array pointers):
#include<stdio.h> void print1(int arr[3][5], int x, int y) { int i = 0; int j = 0; for (i = 0; i < x; i++)// Double loop traverses a two-dimensional array { for (j = 0; j < y; j++) { printf("%d ",arr[i][j]);// printf("%d ". *(*(arr+i)+j) ); } printf("\n"); } } void print2(int(*p)[5], int x, int y)//Since a two-dimensional array turns the address of the first element (the address of a one-dimensional array), a one-dimensional array pointer is required to receive it { int i = 0; int j = 0; for (i = 0; i < x; i++)// t Traverses a two-dimensional array through a double loop { for (j = 0; j < y; j++) { //Printf ("%d", *(*(p+i)+j)); //P is the address of a one-dimensional array (one row), *p is the data where the first row is found, which is the array name of the one-dimensional array // * (p + i), i=0, or the first line, i=1 is the second line, i=2 is the third line // *(p+i)+j is the element on the row printf("%d ",p[i][j]); // *(*(p+i)+j)== p[i][j] First enclose P and I in a bracket to get the address of the first element of a one-dimensional array, and then unreference it to get the "array name". Use one more parenthesis to add and j Put it all together, get it i Line j The address of each element, dereference it, get its value, and print it (note! [] than * High priority) //printf("%d ", *(p[i]+j)) // *(p+i) == arr[i] == p[i] // *(p[i]+j) == p[i][j] } printf("\n"); } } int main() { int arr[3][5] = { { 1, 2, 3, 4, 5 }, { 2, 3, 4, 5, 6 }, {3, 4, 5, 6, 7} }; print1(arr,3,5); The array name here is the first element [{1,2, 3,4, 5}]address First, let's look at two-dimensional arrays as one-dimensional arrays, and let's look at the first row{1,2,3,4,5}Data, our first element (the first element), is treated as a one-dimensional array int a[5] //By analogy, the second row of data is the second element (which is also a one-dimensional array), and the third row is the third element (which is also a one-dimensional array) print2(arr,3,5);// So what passed in was the address of the first element of the array, and it was the address of a one-dimensional array return 0; }
Summary
Int arr[10]//arr is an integer array with 10 elements.
int* parr1[10];//parr1 is an array of pointers, first it is an array with 10 elements, each of which is of type (int*),
int(*parr2)[10]; parr2 is an integer array pointer
Use parentheses to combine * with parr2 first
So parr2 is a pointer to an array of 10 elements, each of which is of type int
int( * parr3 [10] ) [5]
Because () has the highest priority, first judge what is in ()
Parr3 is an array because * and [], [] have higher priority, so parr3 binds to []
Remove parr3[10], leaving int(*) [5], its element type.
Example: int arr[10]; remove arr[10], multiply int, and that's its type (reshape)
What type is int(*) [5]?
Looking closely, you'll see that it's the same as the array pointer int(*p)[10]
Then, we can say that parr3 is an array, there are 10 elements, each element is an integer array pointer, this pointer can point to five elements, each element type is an integer array of int. (We call int(*) [5] integer array pointer type, referred to as array pointer type)
Array parameter, pointer parameter
It's hard to avoid writing code [ array ] perhaps [ Pointer ]Passed to the function, how should the parameters of the function be designed?
One-dimensional Array Pass-Through
#include<stdio.h> void test(int arr[])// OK {} void test(int arr[10])// OK {} void test(int* arr)// OK {} void test2(int* *arr)// OK {} void test2(int* arr[20])// OK 20 here can be omitted as expression above {} int main() { int arr[10] = { 0 }; int* arr2[20] = { 0 }; test(arr); test2(arr2); return 0; }
Two-dimensional Array Pass-Through
#include<stdio.h> void test(int arr[3][5]) // OK {} void test(int arr[][5]) // Rows of OK dimension arrays can be omitted {} void test(int arr[3][]) // Columns of a two-dimensional array of NO cannot be omitted {} void test(int arr[][]) // Columns of a two-dimensional array of NO cannot be omitted {} void test(int* arr) // NO This can only be used to receive element addresses of one-dimensional arrays (the addresses of arrays, to be received with array pointers, not one-level pointers of arrays), and cannot receive parameters of two-dimensional arrays {} void test(int* *arr) // The array name of a two-dimensional array is the address of the first element (the address of the first row, which can be considered the address of a one-dimensional array) {} // The address of an array, which cannot be placed in a secondary pointer // A secondary pointer is the address used to store the first-level pointer variable //So this is also incorrect NO void test(int (*arr)[5]) // ok ()send * and arr First combine to make arr Become a pointer that receives the address of a two-dimensional array (the address of the first element) The address of the first element of a two-dimensional array is the address of the first row of data (can be seen as the address of a one-dimensional array, so an array pointer is required to receive it). The pointer points to an array of five elements (a row of data from a two-dimensional array), each of which is of type int {} int main() { int arr[3][5] = { 0 }; test(arr);// The array name of a two-dimensional array is the address of the first element (the address of the address data in the first row, which is treated as the array name of a one-dimensional array) }
First-level pointer parameter
#include<stdio.h> void print(int* p,int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ",*(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]); print(p,sz);//First-order pointer p passed to function return 0; }
Think: When the parameter part of a function is a first-order pointer, what parameters can a function accept?
#include<stdio.h> void tset(int* p)// Here, the first-order pointer variable p is a copy of the first-order pointer variable in the print function { ; } void print(int* p,int sz) { int a = 10; int* p = &a; test(&a);// ok test(p);// ok, this passes the first-level pointer variable itself, not the address of the first-level pointer, so no second-level pointer is needed to receive it return 0; } Address that accepts first-level pointer variables and a reshaped data
References to secondary pointers
Program 1 (passes the secondary pointer variable itself and the address of the primary pointer variable):
#include<stdio.h> void test(int* *ptr) { printf("num = %d\n",**ptr); } int main() { int n = 10; int* p = &n; int* *pp = &p;// The rightmost *, indicating that P P is a pointer pointing to p; the left int* is a type, which is the type of pointer pointing to p test(pp);// ok, the second-level pointer variable passed here is provincial, so receiving only requires a second-level pointer, which is equivalent to copying a copy of the data test(&p);// ok Here is the address of the first-level pointer variable, the address of the first-level pointer, and the need for a second-level pointer to receive return 0; }
Program 2 (address to pass first-level pointer variable):
#include<stdio.h> void test(int* * p) { printf("hehe"); } int main() { int* ptr = 0; test(&ptr);// Typically, an address (the address that passes a first-level pointer variable) requires a second-level pointer to receive return 0; }
Program 3 (passing the second-level pointer variable itself):
#include<stdio.h> void test(int* * p) // Because the test function passes the second-level pointer variable itself, not the address of the second-level pointer variable, we only need one second-level pointer of the same type to receive the test's parameters // The secondary pointer variable p here is equivalent to a temporary copy of the secondary pointer variable p p { printf("hehe"); } int main() { int* ptr = 0; int* *pp = &ptr; test(pp);// What's passed here is the secondary pointer variable itself return 0; }
Program 4 (array name of pointer array):
#include<stdio.h> void test(int* * p) { printf("hehe"); } int main() { int* arr[10]; test(arr); //Pointer arrays can also be passed, because the type of element stored in the pointer array is int*, that is, the address of the first element is actually the address of a first-level pointer variable (element), the address of a first-level pointer variable, and a second-level pointer variable is required to receive it. return 0; }
Think: When the parameters of a function are binary, what parameters can you accept?
Address of first-level pointer variable Secondary pointer variable itself The name of the array holding the first-level pointer array
Function Pointer
Array pointer, is a pointer to an array Then, the function pointer is a pointer to the function, a pointer to the address of the function.
Procedure 1:
#include<stdio.h> int add(int x, int y) { int z = 0; z = x + y; return z; } int main() { int a = 10; int b = 20; printf("%d\n", add(a, b)); printf("%p\n",&add); printf("%p\n", add);// The output of these two programs is the same. //Since both the function name and the & function name are the addresses of the function, and there is only one function, the address of the function is unique return 0; }
Procedure 2:
#include<stdio.h> int add(int x, int y) { int z = 0; z = x + y; return z; } int main() { int arr[10] = { 0 };// Integer array int(*p)[10] = &arr;// Address of an integer array, requires an integer array pointer to receive int (*pa)(int,int) = add; // Function pointer, which combines * with pa first with (), is a pointer (the pointer stores the address). // The pointer points to a function with two integer parameters, and the function type is int // You just need to tell the function the parameter type, neither x nor y printf("%d\n",(*pa)(2, 3));// 5 (*pa) == add,That is to say add Address, stored in function pointer pa In, we can find it by dereferencing add Function and call it. It's like a function declaration telling you that it can also be called add function return 0; }
Procedure 2:
#include<stdio.h> void print(char* str) { printf("%s\n", str); } int main() { void(*p)(char*) = print; //This is not a dereference. Let's use () to combine * with P and make p a pointer //This pointer points to a function whose parameter is of type char* //Function return type is void //At this point p is our so-called function pointer (*p)("hello word!"); Equivalent to print("hello word!") return 0; } You can think of a function pointer as a function name
Read two interesting passages of code
Code 1
void (*)() - Function Pointer Type ( void (*)() )0, The outermost bracket is the cast symbol, which is to cast 0. int -> Function Pointer Type) At that time 0 would be the address of a function ( * ( void ( * ) ( ) ) 0) *Unreference, call the function at address 0 [ void (*)(),Assume the equation is equivalent to void(*p)(int,int),So you should understand) Is to call the function at address 0 void(*p)(int,int)
Code 2 (simplifies the writing of nested function pointers)
void(*signa1( int, void(*)(int))) (int); signal This is a function declaration signal There are two parameters to the function, the first one is int ,The second is a function pointer, which points to a function whose parameter type is int,The return type is void signal The return type of a function is also a function pointer, which points to a function whose parameter type is int,The return type is void Then we remove the three above (functions) signal,And its two parameters) Be left over: void (*)(int) This is a function pointer type again, it is a function signa1(int, void(*)(int))The return type of typedef void(* pfun_t)(int); Now is the time pfun_t Is the function pointer type // The abbreviation (rename) for pfun_t cannot be placed after it, but should be placed (*here) The renamed function name is written differently between the top and bottom typedef unsigned int uint; // Short form can be written directly after Simplify void(*signa1(int, void(*)(int)))(int); typedef void(*pfun_t)(int); pfun_t signa1(int, pfun_t);
Function Pointer Actual Warfare
#include<stdio.h> int add(int x, int y) { int z = 0; z = x + y; return z; } int main() { int arr[10] = { 0 }; int(*p)[10] = &arr; int (*pa)(int,int) = add;// Function pointer, which combines * with pa first with (), is a pointer (pointer can store address), points to two integer parameters of the function, and then the function type is int // You just need to tell the function the parameter type, neither x nor y printf("%d\n",(*pa)(2, 3));// 5 printf("%d\n", (**pa)(2, 3));// 5 printf("%d\n", (***pa)(2, 3));// 5 For the first time by reason *pa Unquote, through pa Deposited address, found add Function, second time **pa,with*pa Find the address again, and so on. But the output from the three expressions shows that* Not playing its due role So can we get rid of it? * And? printf("%d\n", pa(2, 3));// 5 The result proves that it can The reason is in Procedure 1: printf("%p\n",&add); printf("%p\n", add);// The output of these two programs is the same. //Since both the function name and the & function name are the addresses of the function, and there is only one function, the address of the function is unique So, plus pa It is the address of the equal function ( pa == &add == add),So when using function pointers, you can write function pointer variables directly Sometimes some people add * Why, so readable that the reader can understand pa It's actually a pointer But add * ,Be careful to add(),Otherwise there would be problems, example *pa(2,3),At this time pa Will precede (2),3)Combine to form a function call, then unreference,That is, to dereference result 5 of the call, not what we want return 0; }
Function Pointer Array
#include<stdio.h> int add(int x, int y)// addition { return x + y; } int sub(int x, int y)// subtraction { return x - y; } int mul(int x, int y)// multiplication { return x * y; } int div(int x, int y) //division { return x / y; } int main() { int* arr[5];//The pointer array arr is an array with five elements and each element is of type int*, that is, each element is an integer pointer, int(*pa)(int ,int) = add;// We have four functions to call, which can be cumbersome one after another You need an array that can hold the addresses of four functions - Array of function pointers (provided their parameters and types are identical) int(*parr[4])(int,int) = {add,sub,mul,div};// Function Pointer Array Split the top style into two parts int (*) (int,int) parr[4] Meaning expressed parr First and [4] Together, it becomes an array with four elements, each of which is a function pointer int i = 0; for(i = 0; i < 4; i++) { printf("%d ",parr[i](2, 3));// Add 5, subtract-1, multiply 6, divide 0 } return 0; }
Exercise (Write a function pointer pf that points to my_strcpy)
First, we need to know the type of our custom function: char* my_strcpy(char* dest, const char* src);
Then we transform it: char* (* pf) (char *, const char *) = my_strcpy;
#include<stdio.h> #include<assert.h> char* My_strcopy(char* destination,const char* source)//This is essentially a pointer { assert(destination&&source); char* ret = destination; while (*destination++ = *source++); return ret; } int main() { char arr[30] = { 0 }; char arr1[] = "abc"; char arr2[] = "def"; char arr3[] = "adcde"; char arr4[] = "abcdef"; char* arr5[4] = { arr1, arr2, arr3, arr4 }; char*(*pf)(char*, const char*) = My_strcopy; for (int i = 0; i < 4; i++) { printf("%s\n", pf(arr,arr5[i])); } return 0; }
Write an array of function pointers that hold the addresses of four my_strcpy functions
char* ( * pfarr[4])(char*, const char*);
I don't write this, just like a pointer array, just parenthesize the function name
Next we implement the calculator with an array of function pointers
Normal mode
#include<stdio.h> void menu() { printf("**************************\n"); printf("** 1,add 2.sub ******\n"); printf("** 3,mul 4,div ******\n"); printf("***** 0.Sign out ******\n"); printf("**************************\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; do { menu(); printf("Please select"); scanf("%d",&input); switch (input) { case 1: printf("Enter two operands:"); scanf("%d%d", &x, &y); printf("%d\n",add(x,y)); break; case 2: printf("Enter two operands:"); scanf("%d%d", &x, &y); printf("%d\n",sub(x,y)); break; case 3: printf("Enter two operands:"); scanf("%d%d", &x, &y); printf("%d\n",mul(x,y)); break; case 4: printf("Enter two operands:"); scanf("%d%d", &x, &y); printf("%d\n",div(x,y)); break; case 0: printf("Exit the program"); break; default: printf("Input error, please re-select:"); break; } } while (input); return 0; }
Array of function pointers
#include<stdio.h> void menu() { printf("**************************\n"); printf("** 1,add 2.sub ******\n"); printf("** 3,mul 4,div ******\n"); printf("***** 0.Sign out ******\n"); printf("**************************\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(*parr[])(int, int) = { 0, add, sub, mul, div };// parr is an array of function pointers // Function pointer arrays are also known as transfer tables do { menu(); printf("Please select"); scanf("%d", &input); if (input >= 1) { printf("Enter operands:"); scanf("%d%d", &x, &y); printf("%d\n", parr[input](x, y)); } else if (input == 0) { printf("Exit the program\n"); break; } else { printf("Selection error, please re-enter"); } } while (input); return 0; }
Pointer to array of function pointers
int arr[10]; int(*p)[10] = &arr; // p is a pointer to an integer array //This is an integer array pointer int* (*p)[10] = &arr;// p is a pointer to an array of integer pointers int add(int x, int y) { return x + y; } int(*pf)(int,int) = add;//pf is a function pointer int(*pf[4])(int,int)// This is an array of function pointers int(*(*pf)[4])(int,int)// pf is a pointer to an array of function pointers ()Give Way pf and * First combine to make it a pointer, remove the rest int(*()[4])(int,int)It's obviously an array of function pointers
Pointer to array of function pointers and array of function pointers (detailed)
Function Pointer Array /Write an array first pfarr[5] pfarr[5]; // Reuse () to combine * with array pfarr[5], with - pointer array (*parr[5]); // Rewrite Function Parameter Types and Return Types int(*parr[5])(int, int);// pafarr is an array of function pointers Pointer to array of function pointers *ppfarr = &pfarr;// Address of function pointer array, save, //ppfarr is the pointer to the array of function pointers //Replace it in again, remember to bracket it That is: int(*(*ppfarr)[5])(int, int) = &pfarr; // First use () to combine pparr with *, that is, pparr is a pointer //The pointer looks outward, points to an array [5], and the pparr pointer points to an array //Remove arrays and pointers: int(*) (int, int) This is a function pointer type //Each element of the array is a function pointer type // So ppfarr is a pointer to an array of function pointers int(*p)(int, int); // Function Pointer int(*p[5])(int, int); // Function Pointer Array int(*(*p)[5])(int, int);// Pointer to array of function pointers Pointer to array of function pointers - First it's a pointer, second it's an array, and last it's a function pointer
callback
Callback function: Is a function that is called with a function pointer if you pass the pointer (address) of the function as an argument to another function When this pointer is used to call the function it points to, we call it a callback function. Callback functions are not called directly by the implementer of the function, but by another party when a particular event or condition occurs Used to respond to this event or condition. Simply put, by giving the address of the function to another function, it calls our function. Functional functions cannot be called directly (that is, if you want to play with the computer, you have to ask your parents for permission, or you just play with the shit.)
Example:
#include<stdio.h> void menu() { printf("**************************\n"); printf("** 1,add 2.sub ******\n"); printf("** 3,mul 4,div ******\n"); printf("***** 0.Sign out ******\n"); printf("**************************\n"); } // These are the games you want to play on your computer 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 calc(int(*pf)(int))// This is your parent, your parent agrees (the function receives the address and uses the function) so you can play { int x = 0; int y = 0; printf("Please select two operands:"); scanf("%d%d",&x,&y); printf("%d\n", pf(x, y)); } int main() { int input = 0; do { menu(); printf("Please select"); scanf("%d",&input); switch (input) { case 1: calc(add);//callback This is like when you apply to your parents, turn on the microphone to communicate. break; case 2: calc(sub); break; case 3: calc(mul); break; case 4: calc(div); break; case 0: printf("Exit the program"); break; default: printf("Input error, please re-select:"); break; } } while (input); return 0; }
Use of the qsort function
Let's review bubble sorting: only reshaping data can be sorted
#include<stdio.h> void bubble_sort(int*arr, int sz) { int i = 0; for(i = 0; i < sz - 1; i++)// Whole array, only use the total number of row elements - 1, because no row is needed at the end // It's like 432 1, the larger number in front of 1 goes ahead. // 1 It can only stay here by itself { //One Bubble Sort int j = 0; for (j = 0; j < sz - 1 - i; j++) //Which number is compared to the number behind its bottom { if (arr[j] > arr[j + 1]) // If it's bigger than its butt, it goes one step forward, and then one more time, until it's not bigger than its butt and stops // It's more than nine times, // When it's finished, he'll start to compare with the one who started to compare it with. // Because this ass is better than it, he can't be better than it, because the result is better than a hammer! // So the bottom is less than once, // And the one behind my butt, who's beaten them all, is two times less than nine // And so on { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } int main() { int arr[10] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; 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; }
qsort function-library function-sort-quick sort
First, let's look at the structure type of qsort
void qsort(void *base,Target array (array to sort) size_t num, Number of array elements size_t width,Element size(In bytes) int(*compare)(const void *e1, const void *e2)//Function pointer, which is a comparison function );
Introduction to void *
void * : Universal pointer, can accept any type of data, but can not be called, if you want to call, you can only force type conversion to use #include<stdio.h> #include<stdlib.h> int compare(const void* e1, const void* e2)//Used to compare two integer values // void*untyped pointer, // Pointer of type void*can receive any type of address (pointer), but cannot be dereferenced // Universal Pointer { ; } int main() { int a = 10; void* p = &a; *p = 0;// void* cannot be dereferenced // Because of the pointer's type, it determines how many bytes it can access at a time when it dereferences // Because void* is an untyped pointer, it is not possible to determine how many bytes are accessed at a time when it is dereferenced return 0; }
Enter Actual War
#include<stdio.h> #include<stdlib.h> #include<string.h> int compare(const void* e1, const void* e2) { return *(int*)e1 - *(int*)e2;// Returns 0 if the two perches are equal // The first is less than the second returns a complex number } // The first greater than the second returns a positive number void test() { int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; int sz = sizeof(arr) / sizeof (arr[0]); qsort(arr, sz, sizeof(arr[0]), compare); // qsort sort sort arr, arr has 10 elements, one element memory size, compare the size of two elements, return int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } } int compare_f(const void*e1, const void*e2) { return (int)(*(float*)e1 - *(float*)e2); if (*(float*)e1 == *(float*)e2) { return 0; } else if (*(float*)e1 > *(float*)e2) { return 1; } else { return -1; } } void test2() { float f[] = { 9.0, 8.0, 7.0, 6.0, 5.0, 4.0}; int sz = sizeof(f) / sizeof(f[0]); qsort(f, sz, sizeof(f[0]), compare_f); int i = 0; for (i = 0; i < sz; i++) { printf("%.1f ", f[i]); } } struct stu { char name[20]; int age; }; int compare_by_age(const void*e1, const void*e2) { return ((struct stu*) e1)->age - ((struct stu*)e2)->age; } void test3() { struct stu s[3] = { { "zhangsan", 20 }, { "lisi", 30 }, { "wangwu", 10 } }; int sz = sizeof(s) / sizeof(s[0]); qsort(s, sz, sizeof(s[0]), compare_by_age); int i = 0; for (i = 0; i < sz; i++) { printf("%d ", s[i].age); } } int compare_by_name(const void*e1, const void*e2) { return strcmp( ((struct stu*) e1)->name,((struct stu*)e2)->name);// Name comparison, which is a string comparison, cannot be compared with greater than, equal to, or less than } // The strcmp function is required here // The return value is the same as the return value of size equal, 0, positive, negative void test4() { struct stu s2[3] = { { "zhangsan", 20 },{ "lisi", 30 }, { "wangwu", 10 } }; int sz = sizeof(s2) / sizeof(s2[0]); qsort(s2, sz, sizeof(s2[0]), compare_by_name); int i = 0; for (i = 0; i < sz; i++) { printf("%s ", s2[i].name); } } int main() { test(); printf("\n"); test2(); printf("\n"); test3(); printf("\n"); test4(); return 0; }
qsort (array name, number of elements of the array, size of memory of a single element of the array, (function pointer, address of the function function used to compare the two elements) The two parameters of the function pointer are: address of the two elements to be compared
Improve bubble sorting (callback function)
#include<stdio.h> //The programmer who implements the bubble_sort function, does he know the type of data to sort in the future - does not know //Programmers also do not know the type of the two elements to compare swap(char* buf1, char*buf2, int width) { Our call function is to swap by one byte, one byte Applied qsort The size of the element in the parameter, implemented by int i = 0; for (i = 0; i < width; i++) { char tmp = *buf1; *buf1 = *buf2; *buf2 = tmp; buf1++; buf2++; } } int compare_int(const void*e1, const void*e2) { return *(int*)e1 - *(int*)e2; } void bubble_sort(void*base, int sz, int width, int(*compare)(void*e1, void*e2))// Simulated qsort function { int i = 0; for (i = 0; i < sz; i++) { int j = 0; for (j = 0; j < sz - 1 - i; j++) { //When two elements are compare d, the former is larger than the latter, and the comparison returns a number greater than 0, less than (returns a difference (negative)) equal (returns 0) Greater than, return a positive number, the condition is true, execute if Statement to exchange the positions of two elements, otherwise unchanged. if (compare((char*)base + j*width, (char*)base + (j + 1)*width)>0)// This actually calls the int function name (const void*e1, const void*e2) j It started with 0, base Is the first element, base+(j+1),Is the second element Give them over compare Functions are compared if the first element is larger than the second Then swap, otherwise, don't swap, go up, go back j It's 1, base For the second element, base+(j+1)Is the third element And so on, Be careful!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ((char*)base + j*width,Of char* and width(Width [size of an element], which I've used here qsort Number of elements and size of elements in function parameters, which enable us to traverse elements. j*width Equals skipping several elements (an element's size is width,That multiplies j,Either skip j Element. { //exchange Let's do it with our own swap function swap((char*)base + j*width, (char*)base + (j + 1)*width, width); } } } } void test() { int arr[10] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; int sz = sizeof(arr) / sizeof(arr[0]); // Programmers using bubble_sort must know what data they are sorting //He should know how to compare elements in the array to be sorted bubble_sort(arr, sz, sizeof(arr[0]), compare_int); } struct stu { char name[20]; int age; }; int compare_by_age(const void*e1, const void*e2) { return ((struct stu*) e1)->age - ((struct stu*)e2)->age;// Cast due to arrow priority } void test2() { struct stu s[3] = { { "zhangsan", 20 }, { "lisi", 30 }, { "wangwu", 10 } }; int sz = sizeof(s) / sizeof(s[0]); bubble_sort(s, sz, sizeof(s[0]), compare_by_age); } int compare_by_name(const void*e1, const void*e2) { return strcmp(((struct stu*) e1)->name, ((struct stu*)e2)->name);// Name comparison, which is a string comparison, cannot be compared with greater than, equal to, or less than } // The strcmp function is required here // void test3() { struct stu s[3] = { { "zhangsan", 20 }, { "lisi", 30 }, { "wangwu", 10 } }; int sz = sizeof(s) / sizeof(s[0]); bubble_sort(s, sz, sizeof(s[0]), compare_by_name); } int main() { test(); printf("\n"); test2(); printf("\n"); test3(); return 0; }