当前位置:网站首页>Deep analysis of C language pointer

Deep analysis of C language pointer

2022-07-06 08:32:00 Finally - null

Make a little progress every day , Persistence makes a big difference !!!

Catalog

Preface :

1. Character pointer

2. Pointer array

3. Array pointer

4. Array parameters , The pointer passes the parameter

5. A function pointer

6. Function pointer array

7. A pointer to an array of function pointers

8. Callback function

9. Pointer and array written test exercises

10. Pointer written test exercises

11. summary : 

Preface :

We have learned some simple knowledge about pointers before :

1. The pointer is the address , Is the number that identifies the memory space .

2. Pointer variable is the address used to store the variable , Variables can be found through pointers and stored in memory .

3. The size of the pointer accounts for 4/8 Bytes (32/64).

4. The type of pointer determines how many bytes are skipped when the pointer adds or subtracts integers , Several bytes can be accessed when dereferencing .

5. The operation of the pointer : The number of intermediate elements is obtained by subtracting the pointer from the pointer .

Next, let's continue to explore more about pointers , thorough C Language pointer related content .

1. Character pointer

char*

First use :

Memory layout :

Second use :

Memory layout :

An interview question about character pointer : 

#include<stdio.h>

int main()
{
	char* p1 = "abcdef";
	char* p2 = "abcdef";

	char arr1[] = "abcdef";
	char arr2[] = "abcdef";

	if (p1 == p2)
		printf("p1 == p2\n");
	else
		printf("p1 != p2\n");
	if (arr1 == arr2)
		printf("arr1 == arr2\n");
	else
		printf("arr1 != arr2\n");
	return 0;
}

Explanation of the reason :  because "abcdef" Is a constant string , Put it in the character constant area , Cannot be modified , So there is only one copy in memory , therefore p1 and p2 Are stored first characters a The address of , and arr1 and arr2 Open up two different spaces in the memory to store "abcdef", So the address is different .

2. Pointer array

Concept : reasoning from analogy
Shape array , Used to store shaping numbers , The type of each element is int
A character array , An array used to store characters , The type of each element is char

Pointer array , An array of pointers , The type of each element is data type *
 

application : Print a two-dimensional array

#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 };
	int* parr[3] = { arr1,arr2,arr3 };
	//parr Is an array of integer pointers , The type of each element is int*
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", *(*(parr + i) + j));
		}
		printf("\n");
	}

	return 0;
}

  Memory layout :

 3. Array pointer

Concept : reasoning from analogy :

Shaping the pointer , Address used to store shaping elements  int*p;
Character pointer , Address used to store character elements  char*p;

Array pointer , The address used to store the array   data type (*p)[X];
 

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[10] = &arr;
	//p The first and * Combined description p Is a pointer variable , Then point to a size of 10 Array of elements 
	return 0;
}

notes :& The array name represents the address of the array

The use of array pointers : Improper use

#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[10] = &arr;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(*p + i));// Equivalent to arr[i]
		//*p Get the address of the first element of the array +i Get the address of the next element ,* Get this value 
	}
	return 0;
}

Print one-dimensional arrays using array pointers , More trouble , Not recommended .

Print 2D array

#include<stdio.h>
void print(int(*p)[5], int row, int col)
{
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", *(*(p + i) + j));
			//*(p+i) Get the address of the first element of each line of the two-dimensional array +j Dereference to get every element .
			// Equivalence and 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} };
	print(arr, 3, 5);
	// The array name represents the address of the first element of the array , The first element of a two-dimensional array is a one-dimensional array 
	// So use the array pointer to accept , The address where the array is stored .
	return 0;
}

summary :

int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];

int arr[5] :  It's an array of integers , The array has five elements , The type of each element is int;
int* parr1[10]: It's an array of Pointers , Array has 10 Elements , The type of each element is int*;
int(*parr2)[10]: It's an array pointer , The array pointed to by this pointer is 10 Elements , The type of each element is int
  The type of this pointer variable is int(*)[10];

int(*parr3[10])[5]:parr3 The first and [] The combination shows that this is an array , The array has 10 Elements , The type of each element is int(*)[5]( Array pointer );
 

4. Array parameters , The pointer passes the parameter

1. Array parameters

One dimensional array parameters :

void test1(int arr[])//ok
{}
void test1(int arr[10])//ok
{}
void test1(int*arr)//ok
{}
void test2(int*arr[20])//ok
{}
void test2(int**arr)//ok arr2 Is a pointer accepted with a secondary pointer 
{}
int main()
{
	int arr1[10] = { 0 };
	int* arr2[20] = { 0 };
	test1(arr1);
	test2(arr2);
	return 0;
}

Two dimensional array parameters :

void test(int arr[3][5])//ok
{}
void test(int arr[][])//err  Two dimensional array parameter lines can be omitted , Columns cannot be omitted 
{}
void test(int arr[][5])//ok
{}
void test(int(*arr)[5])//ok  The array name represents the address of the first element , The first element of a two-dimensional array represents the first row of the array ,
                      // Therefore, you can use array pointers to accept 
{}
void test(int**arr)//err  The secondary pointer variable is the address where the primary pointer variable is stored 
{}
void test(int*arr[5])//err Pointer array is used to accept pointers , Cannot accept the address of an array 
{}
int main()
{
	int arr[3][5] = { 0 };
	test(arr);
	return 0;
}

2. The pointer passes the parameter :

First level pointer parameter transfer

void test(int* p)//ok
{}
int main()
{
	int a = 10;
	int* p = &a;
	test(p);
	return 0;
}

The secondary pointer transmits parameters :

void test(int** pp)
{}
int main()
{
	int a = 10;
	int* p = &a;
	int** pp = &p;
	test(pp);//ok
	test(&p);//ok

	return 0;
}

5. A function pointer

The address used to store the function

#include<stdio.h>

int Add(int a, int b)
{
	return a + b;
}
int main()
{
	int a = 10;
	int b = 20;
	int ret = Add(a, b);
	printf("%p\n", Add);
	printf("%p\n", &Add);
	return 0;
}

  How to save the address of a function ?

#include<stdio.h>

int Add(int a, int b)
{
	return a + b;
}
int main()
{
	int (*pf)(int, int) = &Add;//Add;
	//pf It's a function pointer (int,int) The type of function argument 
	int ret = (*pf)(2, 3);
	// Equivalence and (pf)(2,3);
	printf("%d\n", ret);
	return 0;
}

Let's have a deep understanding of function pointers through two pieces of code :

The second piece of code is complex , But there is the same code , A function pointer , So you can use typedef Rename simplified code


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

  The purpose of the function pointer :

Simulate the implementation of a calculator :

#include<stdio.h>
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 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 a = 0;
	int b = 0;
	int ret = 0;
	int input = 0;
	do
	{
		menu();
		printf(" Please select :");
		scanf("%d",&input);
		switch (input)
		{
		case 0:
			printf(" Exit calculator \n");
			break;
		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;
		default:
			printf(" Incorrect input , Please re-enter :\n");
			break;
		}

	} while (input);

	return 0;
}

When we implement calculators , There are many redundant codes in the code , How to avoid these problems ? 

Next, solve the problem of repetition in the code by using function pointers :

Improved code :

#include<stdio.h>
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 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, int))
{
	int a = 0;
	int b = 0;
	int ret = 0;
	printf(" Please enter two operands :");
	scanf("%d%d", &a, &b);
	ret = pf(a, b);
	printf("%d\n", ret);
}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf(" Please select :");
		scanf("%d", &input);
		switch (input)
		{
		case 0:
			printf(" Exit calculator \n");
			break;
		case 1:
			Calc(Add);
			break;
		case 2:
			Calc(Sub);
			break;
		case 3:
			Calc(Mul);
			break;
		case 4:
			Calc(Div);
			break;
		default:
			printf(" Incorrect input , Please re-enter :\n");
			break;
		}

	} while (input);

	return 0;
}

Pass the address of the function , Parameters are accepted with function pointers , Then call this function through the function pointer .

6. Function pointer array

Is an array , An array used to store function addresses

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()
{
	// How to store the addresses of the above four functions into a function pointer array ?
	int(*pf[4])(int, int) = { Add,Sub,Mul,Div };
	//pf The first and [] The combination shows that this is an array , Array has 4 Elements , The type of each element is 
	//int(*)(int,int) A function pointer 
	return 0;
}

Since you can store the address of the function through the function pointer array , So how to use function pointer array to realize calculator ?

#include<stdio.h>
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 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 a = 0;
	int b = 0;
	int ret = 0;
	int(*parr[5])(int,int) = { 0,Add,Sub,Mul,Div };
	do
	{
		menu();
		printf(" Please select :");
		scanf("%d", &input);
		if (input == 0)
		{
			printf(" Exit calculator \n");
		}
		else if (input >= 1 && input < 5)
		{
			printf(" Please enter two operands :");
			scanf("%d%d", &a, &b);
			ret = parr[input](a, b);
			printf("%d\n", ret);
		}
		else
		{
			printf(" Input error , Please re-enter \n");
		}
	} while (input);

	return 0;
}

When using function pointer array, it simplifies the code , And it provides great convenience when modifying the code later

7. A pointer to an array of function pointers

It's a pointer , The address used to store the function pointer array :

int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
int main()
{
	// Function pointer array 
	int(*pfarr[4]) = {Add,Sub,Mul,Div };
	//ppfArr Is a pointer to an array of function pointers 
	//ppfArr The first and * combination , explain ppfArr It's a pointer ,[4] Indicating the pointer 
	// The array pointed to has 4 Elements , The type of each element is int(*)(int,int)
	int(*(*ppfArr)[4])(int, int) = &pfarr;
	return 0;
}

8. Callback function

Above, when we use function pointer to realize calculator , Wrote a Calc Function of , Actually Calc It's a callback function , How to understand callback function ?

A callback function is a function called through a function pointer . If you put a pointer to a function ( Address ) Pass as a parameter to another function , When this pointer is used to call the function it points to , Let's just say this is a callback function . The callback function is not called directly by the function's implementer , It's called by another party when a particular event or condition occurs , Used to respond to the event or condition .
How to sort a group of integer arrays ?
#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		int flag = 1;// If the array to be sorted is already ordered , And then jump out of the loop 
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] < arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	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;
}

Sort in descending order :

When we want to sort a complex object , Obviously, bubble sorting is not applicable , So how to sort a complex object ?

Let's introduce a library function qsort()

#include<stdlib.h>// Include header file 
int main()
{
	void qsort(void* base, // Start position to be sorted 
		size_t num, // Number to be sorted 
		size_t width, // The size of the element to be sorted , Unit is byte 
		int( * cmp)(const void* e1, const void* e2));
	// Is a function pointer , The function pointed to by this function pointer has two parameters ,e1,e2, The function return type is int.
	return 0;
}
//int cmp(const void* e1, const void* e2)
//Return Value Description 
//< 0 e1 less than e2 
//0 e1 equivalent to e2 
//> 0 e1 greater than e2 

Use library functions qsort Sort integer array :

#include<stdlib.h>
#include<stdlib.h>
int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0};
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

The default is ascending :

Use library functions to sort complex objects :

Sort according to one's age :

#include<stdio.h>
#include<stdlib.h>
struct stu
{
	int age;
	char name[20];
};
int by_cmp_age(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
int main()
{
	struct stu s[3] = { {18,"zhangsan"},{20,"lisi"},{19,"wangwu"} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), by_cmp_age);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d ", s[i].name, s[i].age);
		printf("\n");
	}
	return 0;
}

Sort by a person's name

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stu
{
	int age;
	char name[20];
};
int by_cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
int main()
{
	struct stu s[3] = { {18,"zhangsan"},{20,"lisi"},{19,"wangwu"} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), by_cmp_name);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d ", s[i].name, s[i].age);
		printf("\n");
	}
	return 0;
}

Simulate the implementation of library functions qsort:

Implement library functions qsort One of the arguments to is the function pointer , The function parameter pointed to by the function pointer is void* Pointer to type .

Why are they used void* Pointer to type ?

So let's talk about that void* The function of pointer

Simulation Implementation qsort

#include<stdio.h>
#include<string.h>
struct stu
{
	int age;
	char name[20];
};
int by_cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
void bubble_qsort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		int flag = 1;
		for (j = 0; j < sz - 1 - i; j++)
		{
			// Strongly convert the incoming data type to char* Pointer types , Then compare byte by byte 
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}
int main()
{
	struct stu s[3] = { {18,"zhangsan"},{20,"lisi"},{19,"wangwu"} };
	int sz = sizeof(s) / sizeof(s[0]);
	bubble_qsort(s, sz, sizeof(s[0]), by_cmp_name);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d ", s[i].name, s[i].age);
		printf("\n");
	}
	return 0;
}

 

9. Pointer and array written test exercises

One dimensional shaping array :

  One dimensional character array : Array does not contain '\0'

szieof

 strlen:

The array contains '\0'

sizeof:

strlen:

Character pointer :

sizeof:

strlen:

Two dimensional array :

summary :sizeof( Array name ), The array name represents the size of the entire array , Calculate the size of the entire array

& Array name , The array name represents the address of the entire array , besides , All array names represent the address of the first element of the array .

10. Pointer written test exercises

Test question 1 :

Question 2 :

  Question 3 :

  Question 4 :

Question five :

 

Question 6 :

 

  Question 7 :

Question 8 :

 

 

 

11. summary : 

The above is about right C A detailed anatomy of language pointer knowledge points , It contains all the knowledge points about the pointer and the written test questions related to the pointer , I hope I can help each other on the way to study , Common progress , Welcome to comment !!!

原网站

版权声明
本文为[Finally - null]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207060828327366.html