After I first knew the pointer, I started the advanced pointer. In this part of the advanced pointer, I came into contact with a lot of knowledge about pointer. Pointer is really the essence of C language
1, Character pointer
Among the types of pointers, it has been known that there is a pointer type called character pointer char*
General use
int main() { char ch = 'a'; char* pc = &ch; *pc = 'x'; return 0; }
In addition, there is another method of use
int main() { char* ps = "hello word"; //”hello word "is a constant string printf("%s\n", ps); return 0; }
What does "char * PS =" Hello word "mean?
First of all, ps is a character pointer. On a 32-bit platform, the size of the pointer is only four bytes. It is impossible to store the addresses of all elements of the string. In essence, ps stores the address of the first element in the string, and the string cannot be modified. It is best to modify it with const.
Example: the output result of the code
#include <stdio.h> int main() { const char* p1 = "abcd"; const char* p2 = "abcd"; if (p1 == p2) printf("smple\n"); else printf("not smaple\n"); return 0; }
Answer: sample because "abcd" is a constant string and will not be changed again, so when allocating memory, the machine makes p1 and p2 memory have the same address
2, Pointer array
The so-called pointer array is the array that stores pointers.
int arr[5];//integer array char str[5];//Character array int* parr[5];//Array for storing integer pointers -- pointer array char *pstr[5];//Array for storing character type pointers -- pointer array
Case: you can use a pointer array to maintain multiple arrays
#include <stdio.h> int main() { int arr1[5] = { 1,2,3,4,5 }; int arr2[5] = { 2,3,4,5,6 }; int arr3[5] = { 3,4,5,6,7 }; int* arr[] = { arr1,arr2,arr3 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) printf("%d ", *(arr[i] + j)); printf("\n"); } return 0; }
3, Array pointer
As the name suggests, array pointer is a pointer that can point to an array, so how to define an array pointer
int *pa[10]; // The combination priority of '[' and pa is higher than that of '*'. This can only represent that pa represents an array. It should be ensured that pa is combined before '*' int(*pa)[10]; //pa is combined with '*', indicating that pa is a pointer, "int (*) [10]" indicates a pointer to the array, //And the type of the array contains ten elements
Array pointers are useless in one-dimensional arrays, but they can be used to maintain multi-dimensional arrays
Take a two-dimensional array as an example: it is known that the array name of a one-dimensional array represents the address of the first element of the array, while the array name of a two-dimensional array represents all the elements in the first row of the array
Sample (the purpose of this sample is to print a two-dimensional array according to rows and columns)
#include <stdio.h> //Array pointer not used void Printf1(int arr[][4], int m, int n) //In general, the row of two-dimensional array can be omitted, while the column cannot be omitted { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) printf("%d ", arr[i][j]); printf("\n"); } } //Using array pointers void Printf2(int(*pa)[4], int m, int n) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) printf("%d ", *(*(pa + i)+j)); //pa+i represents the address of the line, and then dereference, plus J represents the address of the j-th element of the line //printf("%d ", pa[i][j]); //You can also choose this method, because pa is equivalent to array name arr and is the address of the first element //printf("%d ", *(pa[i] + j)); //printf("%d ",(*(pa + i))[j]); //The results of these methods are the same printf("\n"); } } int main() { int arr[4][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6},{4,5,6,7} }; Printf1(arr, 4, 4); Printf2(arr, 4, 4); return 0; }
Understanding: int (* pa [10]) [5] here, pa represents an array with ten elements stored inside. The type of each element is array pointer. The array pointed to by each array pointer has ten elements stored inside. The type of each element is array integer. pa is the array storing array pointer.
4, Function pointer
Function pointer, that is, a pointer that can point to a function
The function name of a function, which represents the location of a function in memory
#include <stdio.h> int Add(int x, int y) { return x + y; } int main() { printf("%p\n", Add); printf("%p\n", &Add); return 0; }
The output results of the two methods are the same, indicating that the function can also be represented by a pointer. Then how to define a function pointer type? Continue to take the addition function as an example.
#include <stdio.h> int Add(int x, int y) { return x + y; } int main() { //int indicates that the return type of the function is integer, * pad indicates that pad is a pointer, (int,int)Indicates that the function has two integer parameters int (*padd)(int, int) = Add; //Simple use printf("%d\n", (*padd)(3, 5)); printf("%d\n", padd(3, 5)); return 0; }
Note that when defining a function pointer, int (* pad) (int, int). Since the priority of '*' is lower than '('), it should be ensured that pad and '*' are combined first. Otherwise, the combination of pad and '(' indicates that pad is a function
The meaning of the two codes of the underworld
1.(*(void(*)())0)(); 2.void(*signal(int, void(*)(int)))(int);
A string of unique function pointer types in front of 1.0. The pointer points to a function with null parameter and null return value. In front of 0, it means that 0 is forcibly converted to function pointer type, and then 0 is dereferenced to call the function;
2.signal is a function name, which has two parameters, one is an integer, the other is a function pointer, the return type of the function pointer is null, the parameter of the function is integer, the return type of the signal function is a function pointer, and the return type of the function pointer is null;
For the second underworld, the code can be simplified with typedef;
void(*signal(int, void(*)(int)))(int); //This function pointer can be simplified typedef void(* )(int) p_fun; //This way of writing is wrong //Correct writing typedef void(*p_fun)(int); //Simplified results p_fun signal(int,p_fun);
5, Function pointer array
Function pointer array is an array that stores function pointers. It is an array that can store some function pointers with the same parameter types and return value types
int (*pa[4])(int,int) //pa is the internal storage of four function pointers. The parameters pointed to by each function pointer are two integers, and the return values are integers
Application case (simple calculator)
#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; } void menu() { printf("******************************\n"); printf("*******1.+ 2.- ********\n"); printf("*******3.* 4./ ********\n"); printf("******* 0.exit ********\n"); printf("******************************\n"); } int main() { int(*pa[4])(int, int) = { Add,Sub,Mul,Div }; int n; do { menu(); printf("Please select>"); //Select calculation type scanf("%d", &n); if (n >= 1 && n <= 4) { int x, y; printf("Please enter two integers:"); //Number of to be calculated scanf("%d%d", &x, &y); printf("%d\n", pa[n-1](x, y)); //Perform calculations and output results } else if (n == 0) printf("sign out\n"); else printf("Selection error\n"); } while (n); return 0; }
(understand) pointer to function pointer array (persistent doll)
//Function pointer array int(*parr[10])(int, int); //A pointer that holds an array of function pointers int(*(*ppadd)[10])(int, int) = &parr; //Pad represents a pointer. The address it points to is an array with ten elements, //The type of each element is a function pointer. The function pointed to by the function pointer has two integer parameters, and the return type is integer
6, Callback function
1. Use of qsort function
Qsort can sort any type of data. When using qsort function, you need the header file stdlib h; At the same time, when using qsort function, there are four parameters: array name, number of bytes to be sorted, number of bytes occupied by data type, and compare function (you need to define it yourself)
_ACRTIMP void __cdecl qsort( _Inout_updates_bytes_(_NumOfElements * _SizeOfElements) void* _Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ _CoreCrtNonSecureSearchSortCompareFunction _CompareFunction );
Case list, sorting integer data
#include <stdio.h> #include <stdlib.h> int cmp_int(const void* e1, const void* e2) { return *(int*)e1 - *(int*)e2; } //This function is used to determine the callback of qsort function to this function when qsort function is used. The purpose is to determine the direction of the transmitted address //The size of the two numbers. If the first number is greater than the second number, return the number less than zero, equal return 0, and less than return the number less than zero //Therefore, return *(int*)e1 - *(int*)e2 can be used perfectly. int main() { int arr[] = { 12,121,34,2,33,45,87,91,21,12 }; int sz = sizeof(arr) / sizeof(arr[0]); //Judge the number of elements qsort(arr, sz, sizeof(int), cmp_int); return 0; }
For structure types, you can also use
The purpose of the case is to sort according to the age
#include <stdio.h> #include <stdlib.h> struct stu { char namr[30]; int age; }; int cmp_age(const void* e1, const void* e2) { return ((((struct stu*)e1)->age) - (((struct stu*)e2)->age)); //If you need to arrange the names in dictionary order, you only need to turn the situation into that the pointer of the structure type points to the name part } int main() { struct stu s[3] = { {"zhangsan",13},{"lisi",15},{"wangwu",12} }; int sz = sizeof(s) / sizeof(s[0]); qsort(s, sz, sizeof(s[0]), cmp_age); return 0; }
2. Simulate and implement the function (sorting method: bubble sorting)
#include <stdio.h> struct stu { char name[20]; int age; }; int cmp_int(const void* e1, const void*e2) { return *((int*)e1) - *((int*)e2); } int cmp_age(const void* e1, const void* e2) { return ((((struct stu*)e1)->age) - (((struct stu*)e2)->age)); } void swap(char* buf1,char*buf2,int wide) //Because you don't know the type of the two elements, you need to know the width of the array elements. Only one byte is exchanged at a time, and the width is exchanged times { for (int i = 0; i < wide; i++) { char tmp = *buf1; *buf1 = *buf2; *buf2 = tmp; buf1++; buf2++; } } void bubble_sort(void* base, int sz, int wide,int(*cmp)(void* e1,void* e2)) //The void * pointer can accept any type of data, and a function pointer can accept the comparison methods of different types of data { for (int i = 0; i < sz - 1; i++) //Judge the number of trips { for (int j = 0; j < sz - i - 1; j++) //The number of times each element needs to be compared with other elements { if (cmp(((char*)base + j * wide), ((char*)base + (j + 1)*wide)) > 0) //Because we don't know the type of the accepted element and can't process the address directly, we forcibly convert the base to the character pointer type //The character data only occupies one byte and the width of the array element is known. In this way, the next element can be found and compared { swap(((char*)base + j * wide), ((char*)base + (j + 1)*wide),wide); //If the conditions are met, the two elements are exchanged } } } } void test() { int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr,sz,sizeof(arr[0]),cmp_int); } void test1() { struct stu s[3] = { {"zhangsan",12},{"lisi",11},{"wangwu",13} }; int sz = sizeof(s) / sizeof(s[0]); bubble_sort(s, sz, sizeof(s[0]), cmp_age); } int main() { test1(); test(); return 0; }