Section 2. Advanced pointer
1. Character pointer
Among the pointer types, we know that one pointer type is character pointer char *;
be careful:
const char* pstr = "hello";
Instead of putting the string hello into the character pointer pstr, the essence is to put the address of the first character of the string hello into pstr.
#include <stdio.h> int main() { char str1[] = "hello"; char str2[] = "hello"; const char *str3 = "hello"; const char *str4 = "hello"; 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; } //str1 and str2 are not same //str3 and str4 are same
Here, str3 and str4 point to the same constant string.
C/C + + will store the constant string in a separate memory area when several pointers. When pointing to the same string, they actually point to the same block of memory. However, when initializing different arrays with the same constant string, different memory blocks will be opened up.
So str1 and str2 are different, and str3 and str4 are the same.
2. Pointer array
Pointer array is an array of pointers.
int* arr1[10]; //Array of integer pointers char* arr2[10]; //Array of first level character pointers char** arr3[10];//Array of secondary character pointers
3. Array pointer
3.1 definitions
Array pointers are pointers that can point to arrays.
int (*p)[10]; //Explanation: P is first combined with * to indicate that P is a pointer variable, and then points to an array of 10 integers. So p is a pointer to an array, called an array pointer. //Note here that the priority of [] is higher than that of * sign, so () must be added to ensure that p is combined with * first.
3.2 "array name" vs "& array name"
int arr[10];
Are arr and & arr the same thing?
for instance:
#include <stdio.h> int main() { int arr[10] = { 0 }; printf("arr = %p\n", arr); printf("arr+1 = %p\n", arr+1); printf("&arr= %p\n", &arr); printf("&arr+1= %p\n", &arr+1); return 0; }
result:
arr = 012FF6EC
arr+1 = 012FF6F0
&arr= 012FF6EC
&arr+1= 012FF714
From the results of the above code, we can see that & arr and arr have the same value, but they are essentially different.
actually:
arr is the array name, which indicates the address of the first element of the array.
&Arr represents the address of the array, not the address of the first element of the array.
In this example, the type of & arr is int(*)[10], which is an array pointer type
The address of the array is + 1, skipping the size of the entire array, so the difference between & arr + 1 and & arr is 40
4. Function pointer
#include <stdio.h> void test() { printf("hello\n"); } int main() { printf("%p\n", test); printf("%p\n", &test); return 0; }
result:
003A1474
003A1474
Two addresses are output, which are the addresses of the test function. So, how to save the address of the function?
void test() { printf("hehe\n"); } void (*pfun)(); //pfun is a pointer to a function
Add two interesting pieces of code:
//Code 1 ( *( void (*)() )0 )(); //Convert 0 to function pointer type without reference and no return value, and then invoke 0 after invoking. //Is to call the function at address 0 //Code 2 void ( *signal( int , void(*)(int) ) )(int); //signal is a function declaration //This function has two parameters, one is int and the other is a function pointer. The function parameter pointed by the pointer is int and the return type is void //The return type of signal function is also a function pointer. The pointer points to the function parameter int, and the return type is void //Simplified version typedef void(* pfun_t)(int); pfun_t signal(int,pfun_t);
5. Function pointer array
Array is a storage space for storing the same type of data, and pointer array is an array for storing pointers.
If the address of the function is stored in an array, this array is called the function pointer array.
int (*parr[10])();
Purpose of function pointer array: transfer table
example:
Use the function pointer array to implement the calculator.
#include <stdio.h> int add(int a,int b){ return a+b; } int sub(int a,int b){ return a-b; } int mul(int a,int b){ return a*b; } int div(int a,int b){ return a/b; } int main(){ int x, y; int input = 1; int ret = 0; int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //Transfer table while (input){ printf( "*************************\n" ); printf( " 1:add 2:sub \n" ); printf( " 3:mul 4:div \n" ); printf( "*************************\n" ); printf( "Please select:" ); scanf( "%d", &input); if ((input <= 4 && input >= 1)){ printf("Input operand:"); scanf("%d %d", &x, &y); ret = (*p[input])(x, y); }else{ printf( "Incorrect input\n" ); } printf( "ret = %d\n", ret); } return 0; }
6. 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
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)[5])(const char*) = &pfunArr; return 0; }
7. 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 the pointer is used to call the function it points to, we say it is a callback function.
The callback function is not called directly by the implementer of the function, but by another party when a specific event or condition occurs, which is used to respond to the event or condition.
for instance:
First, demonstrate the use of qsort function (quick sort):
The qsot function can sort any type of data
#include <stdio.h> //The user of the qosrt function must implement a comparison function //void * is a pointer without a specific type //The pointer variable of void * can store any type of address //The pointer of void * cannot be dereferenced and + - * / directly int int_cmp(const void * p1, const void * p2){ return (*( int *)p1 - *(int *) p2); } int main(){ int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; int i = 0; qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp); for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++){ printf( "%d ", arr[i]); } printf("\n"); return 0; }
Use the callback function to simulate the implementation of qsort (bubbling)
#include <stdio.h> //Comparison function int int_cmp(const void * p1, const void * p2){ return (*( int *)p1 - *(int *) p2); } void _swap(void *p1, void * p2, int size){ int i = 0; for (i = 0; i< size; i++){ char tmp = *((char *)p1 + i); *(( char *)p1 + i) = *((char *) p2 + i); *(( char *)p2 + i) = tmp; } } void bubble(void *base, int count , int size, int(*cmp )(void *, void *)){ int i = 0; int j = 0; for (i = 0; i< count - 1; i++){ for (j = 0; j<count-i-1; j++){ if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0){ _swap(( char *)base + j*size, (char *)base + (j + 1)*size, size); } } } } int main(){ int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; //char *arr[] = {"aaaa","dddd","cccc","bbbb"}; int i = 0; bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp); for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++){ printf( "%d ", arr[i]); } printf("\n"); return 0; }
8. Written test questions for pointers and arrays
X86 environment
(the address size is 4 in X86 environment and 8 in X64 environment)
//One dimensional array int a[] = {1,2,3,4}; printf("%d\n",sizeof(a)); //16 (the array name a is placed separately in sizeof to calculate the size of the whole array) printf("%d\n",sizeof(a+0)); //4 (a represents the address of the first element, and a+0 also represents the address of the first element) printf("%d\n",sizeof(*a)); //4 (* a indicates dereference of the first element address) printf("%d\n",sizeof(a+1)); //4 (a represents the address of the first element, and a+1 represents the address of the second element) printf("%d\n",sizeof(a[1])); //4 (a[1] is the second element of the array) printf("%d\n",sizeof(&a)); //4 (& A represents the address of the array) printf("%d\n",sizeof(*&a)); //16 (* & A indicates dereference to the address of the array) printf("%d\n",sizeof(&a+1)); //4 (& A + 1 address after skipping the entire array) printf("%d\n",sizeof(&a[0])); //4 (& A [0] indicates the address of the first element of the array) printf("%d\n",sizeof(&a[0]+1)); //4 (& A [0] + 1 indicates the address of the second element of the array) //Character array char arr[] = {'a','b','c','d','e','f'}; printf("%d\n", sizeof(arr)); //6 printf("%d\n", sizeof(arr+0)); //4 printf("%d\n", sizeof(*arr)); //1 printf("%d\n", sizeof(arr[1])); //1 printf("%d\n", sizeof(&arr)); //4 printf("%d\n", sizeof(&arr+1)); //4 printf("%d\n", sizeof(&arr[0]+1)); //4 printf("%d\n", strlen(arr)); //Random value because there is no '\ 0' at the end printf("%d\n", strlen(arr+0)); //Random value because there is no '\ 0' at the end printf("%d\n", strlen(*arr)); //If an error is reported, strlen will take 97 ('a 'ascii value) as the starting address statistics string, resulting in memory access conflict printf("%d\n", strlen(arr[1])); //Error reporting, ibid printf("%d\n", strlen(&arr)); //Error reported, & arr is the address of the ARR array, which does not match the parameter type printf("%d\n", strlen(&arr+1)); //Error reporting, ibid printf("%d\n", strlen(&arr[0]+1)); //Random value because there is no '\ 0' at the end //sizeof is an operator of any type //sizeof gets the storage space occupied by the data in the memory, which is counted in bytes //strlen is a library function for strings //strlen focuses on the position of '\ 0' in the string and calculates the number of characters before '\ 0' char arr[] = "abcdef"; printf("%d\n", sizeof(arr)); //7 printf("%d\n", sizeof(arr+0)); //4 printf("%d\n", sizeof(*arr)); //1 printf("%d\n", sizeof(arr[1])); //1 printf("%d\n", sizeof(&arr)); //4 printf("%d\n", sizeof(&arr+1)); //4 printf("%d\n", sizeof(&arr[0]+1)); //4 printf("%d\n", strlen(arr)); //6 printf("%d\n", strlen(arr+0)); //6 printf("%d\n", strlen(*arr)); //If an error is reported, strlen will take 97 ('a 'ascii value) as the starting address statistics string, resulting in memory access conflict printf("%d\n", strlen(arr[1])); //Error reporting, ibid printf("%d\n", strlen(&arr)); //Error reported, & arr is the address of the ARR array, which does not match the parameter type printf("%d\n", strlen(&arr+1)); //Error reporting, ibid printf("%d\n", strlen(&arr[0]+1)); //5 char *p = "abcdef"; printf("%d\n", sizeof(p)); //4 printf("%d\n", sizeof(p+1)); //4 printf("%d\n", sizeof(*p)); //1 printf("%d\n", sizeof(p[0])); //1 printf("%d\n", sizeof(&p)); //4 printf("%d\n", sizeof(&p+1)); //4 printf("%d\n", sizeof(&p[0]+1)); //4 printf("%d\n", strlen(p)); //6 printf("%d\n", strlen(p+1)); //5 printf("%d\n", strlen(*p)); //report errors printf("%d\n", strlen(p[0])); //report errors printf("%d\n", strlen(&p)); //report errors printf("%d\n", strlen(&p+1)); //report errors printf("%d\n", strlen(&p[0]+1)); //5 //Two dimensional array int a[3][4] = {0}; printf("%d\n",sizeof(a)); //48 printf("%d\n",sizeof(a[0][0])); //4 printf("%d\n",sizeof(a[0])); //16 printf("%d\n",sizeof(a[0]+1)); //4 printf("%d\n",sizeof(*(a[0]+1))); //4 printf("%d\n",sizeof(a+1)); //4 printf("%d\n",sizeof(*(a+1))); //16 printf("%d\n",sizeof(&a[0]+1)); //4 printf("%d\n",sizeof(*(&a[0]+1))); //16 printf("%d\n",sizeof(*a)); //16 printf("%d\n",sizeof(a[3])); //16
Summary:
Meaning of array name:
- Sizeof (array name), where the array name represents the entire array, and the size of the entire array is calculated.
- &Array name, where the array name represents the whole array, and the address of the whole array is taken out.
- In addition, all array names represent the address of the first element.
9. Pointer written test questions
Written test question 1
int main(){ int a[5] = { 1, 2, 3, 4, 5 }; int *ptr = (int *)(&a + 1); printf( "%d,%d", *(a + 1), *(ptr - 1)); return 0; } //2,5
Written test question 2
struct Test{ int Num; char *pcName; short sDate; char cha[2]; short sBa[4]; }*p; int main(){ printf("%p\n", p + 0x1); printf("%p\n", (unsigned long)p + 0x1); printf("%p\n", (unsigned int*)p + 0x1); return 0; } //00000014 //00000001 //00000004
Written test question 3
int main(){ int a[4] = { 1, 2, 3, 4 }; int *ptr1 = (int *)(&a + 1); int *ptr2 = (int *)((int)a + 1); printf( "%x,%x", ptr1[-1], *ptr2); return 0; } //4,2000000
Written test question 4
int main(){ int a[3][2] = { (0, 1), (2, 3), (4, 5) }; int *p; p = a[0]; printf("%d", p[0]); return 0; } //1
Written test question 5
int main(){ int a[5][5]; int(*p)[4]; p = a; printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]); return 0; } //FFFFFFFC,-4
Written test question 6
int main(){ int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int *ptr1 = (int *)(&aa + 1); int *ptr2 = (int *)(*(aa + 1)); printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1)); return 0; } //10,5
Written test question 7
int main(){ char *a[] = {"work","at","alibaba"}; char**pa = a; pa++; printf("%s\n", *pa); return 0; } //at
Written examination question 8
int main(){ char *c[] = {"ENTER","NEW","POINT","FIRST"}; char**cp[] = {c+3,c+2,c+1,c}; char***cpp = cp; printf("%s\n", **++cpp); printf("%s\n", *--*++cpp+3); printf("%s\n", *cpp[-2]+3); printf("%s\n", cpp[-1][-1]+1); return 0; } //POINT //ER //ST //EW
10. Appendix (use of qsort)
#include<string.h> #include<stdio.h> #include<stdlib. h> / / header file for qsort struct Student{ int id; char name[50]; }; int int_cmp(const void* a, const void* b){ return *(int*)a - *(int*)b; } int char_cmp(const void* a, const void* b){ return *(char*)a - *(char*)b; } int double_cmp(const void* a, const void* b){ return *(double*)a > *(double*)b ? 1 : -1; } int struct_cmp(const void* a, const void* b) { return ((struct Student*)a)->id - ((struct Student*)b)->id; } int str_cmp(const void* a, const void* b) { return strcmp(*(char**)a, *(char**)b); } int main() { //int sort int num[5] = { 1,3,9,5,2 }; qsort(num, sizeof(num) / sizeof(num[0]), sizeof(num[0]), int_cmp); for (int i = 0; i < sizeof(num) / sizeof(num[0]); i++) { printf("%d ", num[i]); } printf("\n"); //char sort char word[5] = "CADB"; qsort(word, sizeof(word) / sizeof(word[0]), sizeof(word[0]), char_cmp); for (int i = 0; i < sizeof(word) / sizeof(word[0]); i++) { printf("%c ", word[i]); } printf("\n"); //double sort double in[5] = { 1.23,3.14159,2.6,5.74,4.11 }; qsort(in, sizeof(in) / sizeof(in[0]), sizeof(in[0]), double_cmp); for (int i = 0; i < sizeof(in) / sizeof(in[0]); i++) { printf("%lf ", in[i]); } printf("\n"); //struct sort struct Student stu[3] = { {2,"Xiao Ming"},{1,"petty thief"},{3,"Xiao Hong"} }; qsort(stu, sizeof(stu) / sizeof(stu[0]), sizeof(stu[0]), struct_cmp); for (int i = 0; i < sizeof(stu) / sizeof(stu[0]); i++) { printf("%d%s ", stu[i].id,stu[i].name); } printf("\n"); //string sort char *str[5] = { "AAA","EEE","CCC","BBB","DDD" }; qsort(str, sizeof(str) / sizeof(str[0]), sizeof(str[0]), str_cmp); for (int i = 0; i < sizeof(str) / sizeof(str[0]); i++) { printf("%s ", str[i]); } printf("\n"); return 0; }