Advanced pointer of C language

Keywords: C C++ Back-end

preface

1. Pointer is a variable used to store address. The address uniquely identifies a piece of memory space.
2. The size of the pointer is fixed 4 / 8 bytes (32-bit operating system / 64 bit operating system).
3. Pointers are typed. The type of pointer determines the step size of ± integer and the permission of operation memory size when pointer dereference.
4. Pointer operation.

Tip: the following is the main content of this article. The following cases can be used for reference

1, Character pointer

Character pointer char in pointer type*
Example:

int main()
{
	char a = 'a';
	char* p = &a;
	return 0;
}
int main()
{
	char arr[] = "abcdef";
	char* p = arr;
	printf("%s\n", arr);	//Output abcdef
	printf("%s\n", p);		//Output abcdef
	return 0;
}

//There is another way to write
void test()
{
	//abcdef is a constant
	char* p = "abcdef";
	//p is the address of the first element
	printf("%c\n", *p);	//Output a
	printf("%c\n", p);	//Output abcdef
}

Related interview questions

int main()
{
	char arr1 = "abcdef";
	char arr2 = "abcdef";

	char* p1 = "abcdef";
	char* p2 = "abcdef";

	if (arr1 == arr2)
	{
		printf("arr1 = arr2");
	} 
	else
	{
		printf("arr1 != arr2");
	}

	if (p1 == p2)
	{
		printf("p1 = p2");
	} 
	else
	{
		printf("p1 != p2");
	}
	return 0;

	//1. Output arr1 = arr2
	//2. Output p1 = p2
	//Because char* p1 = "abcdef";
	//char* p2 = "abcdef";
	//abcdef is a constant, so P1 and P2 point to the same location of the first element
}

2, Array pointer

Is the array pointer an array? Or a pointer? The answer is: pointer.

int main()
{
	int* p = NULL; //The shaping pointer points to the shaping pointer, which can store the shaping address
	char* cp = NULL; //Character pointer pointer to a character 	 Address where characters can be stored
	
	int arr[10] = {0}; //Array pointer a pointer to an array that can hold the address of the array
	//Arr and arr[0] are the first element addresses  
	//&Arr is the address of the array
	return 0;
}

Array pointer:

int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	int (*p)[10] = &arr;
	return 0;
}

Exercise of using array pointer:

void print(int (*p)[5], int row, int col)
{
    for( int i = 0; i < row; i++ )
    {
        //printf("%p \n", *(p + i)); // Address of each line
        for( int j = 0; j < col; j++ )
        {
            printf("%d ", *(*(p + i) + j)); //Each row, each element
            //printf("%d ", (*(p + i))[j]); // Each row, each element
            //printf("%d ", p[i][j]); // Each row, each element
        }
        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);
    return 0;
}

3, Pointer array

Pointer array is an array used to store pointers

int main()
{
	int arr[10] = { 0 }; //Shaping array
	char ch[10] = { 0 }; //Character array

	int* pArr[10];	//Integer pointer array
	char* cArr[10];	//Character pointer array
	
	return 0;
}

Use of pointer array

int main()
{
	int arr1[] = {1, 2, 3, 4, 5};
	int arr2[] = {6, 7 ,8 ,9 , 0};
	int arr3[] = {12, 23, 34, 45, 56};
	
	//Pointer array
	int* pArr[] = {arr1, arr2, arr3};
	
	//Gets each element of three arrays
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ", *(pArr[i] + j));
		}
		printf("\n");
	}
	return 0;
}

4, Array parameter passing and pointer parameter passing

One dimensional array

void test1(int arr[]){}			//ok? ok
void test1(int* arr[]){}		//ok? ok
void test1(int arr[10]){}		//ok? ok
void test2(int *arr[20]){}		//ok? ok
void test2(int **arr){}			//ok? ok

int main()
{
	int arr[10] = {0};
	int* arr2[20] = {0};
	test1(arr);
	test2(arr2);
	return 0;
}

Two dimensional array

void test(int *arr){} //ok? err! 
void test(int *arr[5]){} //ok? err!
void test(int (*arr)[5]){} //ok? ok!
void test(int **arr){} //ok? err!

int main()
{
	int arr[3][5] = {0};
	test(arr);
	return 0;
}

Secondary pointer transfer parameter

void test(int** pp)
{}

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

5, Function pointer

Pointer to function
&Both the function name and the function name are the address of the function

int Add(int x, int y)
{
	return x + y;
}

void Print(char* str)
{
    printf("%s ", str);
}

int main()
{
	int a = 10;
	int b = 20;
	
	int (*p)(int, int) = Add;
	int ret = (*p)(a, b);
    printf("%d\n", ret);

    void (*p2)(char*) = Print;
    (*p2)("hello world");
	return 0;
}

6, 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()
{
	int (*parr[4])(int, int) = {Add, Sub, Mul, Div};

	for (int i = 0; i < 4; i++)
	{
		int result = parr[i](10, 20);
		printf("%d\n", result);
	}
	
	return 0;
}

practice:
char* my_strcpy(char* dest, const char* src)
Write a function pointer and function pointer array, the array length is 4

#include <stdio.h>

char* my_strcpy(char* dest, const char* src)
{

}

int main()
{
    char* (*pf)(char*, const char*) = my_strcpy;
    char* (*pf[4])(char*, const char*);
}

The function pointer array case implements a calculator:
Write a function pointer array first:

#include <stdio.h>
void menu()
{
	printf("***************************\n");
	printf("*****1. add 	2. sub ****\n");
	printf("*****3. mul		4. div ****\n");
	printf("***** 		0. ext 	   ****\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("Please enter two operands:>");
                scanf("%d%d", &x,&y);
				printf("%d\n", Add(x, y));
                break;
			case 2:
                printf("Please enter two operands:>");
                scanf("%d%d", &x,&y);
				printf("%d\n", Sub(x, y));
				break;
			case 3:
                printf("Please enter two operands:>");
                scanf("%d%d", &x,&y);
				printf("%d\n", Mul(x, y));
				break;
			case 4:
                printf("Please enter two operands:>");
                scanf("%d%d", &x,&y);
				printf("%d\n", Div(x, y));
				break;
			case 0:
				printf("sign out\n");
                break;
			default:
				printf("Input error, please re-enter");
				break;
		}
	}
	while(input);
	return 0;
}

After using the function pointer array:

#include <stdio.h>
//The menu, add, sub, Mul and div functions are the same as those above, so they are omitted. The main function is changed
void menu()
{
	printf("***************************\n");
	printf("*****1. add 	2. sub ****\n");
	printf("*****3. mul		4. div ****\n");
	printf("*****5. xor			   ****\n");
	printf("***** 		0. ext 	   ****\n");
	printf("***************************\n");
}

//At this point, if we want to add another bit operation method
//There is no need to change a lot of code and it is easier to maintain
int Xor(int x, int y)
{
	return x ^ y;
}

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;

    int (*pf[])(int, int) = {0, Add, Sub, Mul, Div, Xor};

	do
	{
		menu();
		printf("Please select:>");
		scanf("%d", &input);

        if (input >= 1 && input <= 5)
        {
            printf("Please enter two operands:>");
            scanf("%d%d", &x, &y);
            int result = pf[input](x, y);
            printf("%d\n", result);
        }
        else if (input == 0)
        {
            printf("sign out\n");
        }
        else
        {
            printf("Input error,Please re-enter");
        }
		
	}
	while(input);
	return 0;
}

7, Pointer function pointer array pointer

int main()
{
	int arr[10] = {0};
	int (*p)[10] = &arr; //Pointer array
	
	int (*pfArr[4])(int, int); //pfArr is an array of function pointers
	int (*(*ppfArr)[4])(int, int) = &pfArr;//Pointer to array of function pointers
	//ppfArr is an array pointer. The array pointed to by the pointer has four elements 
	//The type of each element of the array pointed to is a function pointer
	//The type of that function pointer is int(*)(int, int)
	return 0;
}

8, Callback function

A callback function is a function called through a function pointer.
Case:
For example, the Switch case implementation in the function pointer array above has a lot of redundant code, which can be optimized by callback function.

#include <stdio.h>
void menu()
{
	printf("***************************\n");
	printf("*****1. add 	2. sub ****\n");
	printf("*****3. mul		4. div ****\n");
	printf("***** 		0. ext 	   ****\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 (*fp)(int, int))
{
    int x = 0;
	int y = 0;
    printf("Please enter two operands:>");
    scanf("%d%d", &x,&y);
    printf("%d \n", fp(x, y));
}

int main()
{
	int input = 0;
	
	do
	{
		menu();
		printf("Please select:>");
		scanf("%d", &input);
		switch(input)
		{
			case 1:
                Calc(Add);
                break;
			case 2:
                Calc(Sub);
				break;
			case 3:
                Calc(Mul);
				break;
			case 4:
                Calc(Div);
				break;
			case 0:
				printf("sign out\n");
                break;
			default:
				printf("Input error, please re-enter");
				break;
		}
	}
	while(input);
	return 0;
}

Case 2:

//Use of qsort function
void qsort(void *base,
		   size_t num,
		   size_t width,
		   int(*cmp)(const void *e1, const void *e2)
		   );

Let's write a simple bubble sort first, so that we can know what to do next

void bubble_sort(int arr[], int sz)
{

	for(int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

int main()
{
	int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
	int sz = sizeof(arr)/sizeof(arr[0]);
	bubble_sort(arr, sz);

	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

However, we found that bubble sorting can only sort integer arrays. If the array to be sorted is a float type array or structure array or any other type of array, sorting cannot be realized.
The C library function qsort just solves this problem. Let's see how it is used.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*test1,2,3,4 Functions bubble sort with different data types*/
int cmp_int(const void* e1, const void* e2)
{
	//Compare two shaping values
	return *(int*)e1 - *(int*)e2;
}

int cmp_float(const void* e1, const void* e2)
{
	//Compare two shaping values
	return ((int)(*(float*)e1 - *(float*)e2));
}

void test1()
{
    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]), cmp_int);

	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
    printf("\n");
}

void test2()
{
    float arr[] = {9.0, 8.0, 7.0, 6.0, 5.0};
	int sz = sizeof(arr)/sizeof(arr[0]);

	qsort(arr, sz, sizeof(arr[0]), cmp_float);

	for (int i = 0; i < sz; i++)
	{
		printf("%f ", arr[i]);
	}
    printf("\n");
}

struct Stu
{
    char name[20];
    int age;
};

int cmp_stu_by_age(const void*e1, const void*e2)
{
    return ((struct Stu*)e1) -> age - ((struct Stu*)e2) -> age;
}

int cmp_stu_by_name(const void*e1, const void*e2)
{
    //Compare strings using the strcmp function of the string library function
    return strcmp(((struct Stu*)e1) -> name, ((struct Stu*)e2) -> name);
}

void test3()
{
    struct Stu stu[3] = { {"Zhang San", 33 }, {"Li Si", 22 }, { "Wang Wu", 11 } };
    int sz = sizeof(stu)/sizeof(stu[0]);
    qsort(stu, sz, sizeof(stu[0]), cmp_stu_by_age);
    for (int i = 0; i < sz; i++)
	{
		printf("%s ", stu[i].name);
	}
}

void test4()
{
    struct Stu stu[3] = { {"Zhang San", 33 }, {"Li Si", 22 }, { "Wang Wu", 11 } };
    int sz = sizeof(stu)/sizeof(stu[0]);
    qsort(stu, sz, sizeof(stu[0]), cmp_stu_by_name);
    for (int i = 0; i < sz; i++)
	{
		printf("%d ", stu[i].age);
	}
}

int main()
{
	test1();
    test2();
    test3();
    test4();
	return 0;
}

Write a qsort function

#include <stdio.h>

struct Stu
{
	char name[20];
	int age;
};

void Swap(char* buf1, char* buf2, int width)
{
	for (int i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void my_qsort(void* base, int sz, int width, int (*cmp)(void* e1, void* e2))
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char*)base + j*width, (char*)base + (j + 1)*width) > 0)
			{
				//Swap two elements
				Swap((char*)base + j*width, (char*)base + (j + 1)*width, width);
			}
		}
	}
}

int cmp_stu_by_age(const char* el1, const char* el2)
{
	return ((struct Stu*)el1) -> age - ((struct Stu*)el2) -> age;
}

int main()
{
	struct Stu stu[] = { { "Zhang San", 20 }, { "Li Si", 18 } };
	
	int sz = sizeof(stu) / sizeof(stu[0]);

	my_qsort(stu, sz, sizeof(stu[0]), cmp_stu_by_age);

	for (int i = 0; i < sz; i++)
	{
		printf("%s\n", stu[i].name);
	}
	return 0;
}


Posted by steved on Thu, 02 Dec 2021 12:25:37 -0800