Pointer to various applications [real interview questions of large factories]

Posted by rharter on Wed, 26 Jan 2022 18:34:39 +0100

Analysis of various applications of pointer and real interview questions of large factories

preface

Most of the pointers learned by beginners or ordinary colleges and universities are simple, that is, we understand that the pointer is an address. We can operate the address content through dereference operation, which is often limited to simple variables and arrays. However, we should have a clear and further understanding of the pointer, and there are many knowledge we have not yet set foot in. This paper will make a simple and systematic summary of the pointer, and attach several real interview questions to help you understand and master. We are full of dry goods. Please support us.

1, The pointer we currently have

1. Character pointer

The pointer type is char*
usage method

int main()
{
	char ch = 'w';
	char* pc = &ch;
	*pc = 'w';
	return 0;
}

Another

int main()
{
	const char* ps = "hello";
	printf("%s\n", ps);
	return 0;
}

Operation results

This actually means that the address of the first element of 'hello' is stored in the pointer variable ps.

Print as% s string to find the first element through the address, and print the string array with backward addressing

Related interview questions

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 array names. The array name shows the address of the first element of the array, but str1 and str2 are two different arrays, except that all the elements in them are the same and open up different address spaces. Therefore, they are different
Although str3 and str4 are different variable names, they both point to the character constant of 'hello'. C/C + + will store the constant string in a separate memory area as several pointers. When pointing to the same string, they will actually point to the same block of memory. So they are the same

Extension: const modifier pointer

const modifier pointer has three cases

const is on the left

const int* pi;
int const* pi;
//In this type, * pi means that pointer variables are often defined, * pi means that the content pointed to by the address cannot be changed, but the address pointed to by the content can be changed

const is on the right of *

int * const h;
//Above the category, address h cannot be changed, but h dereference * h can be changed

const is around *

const int * const k;//The two are equivalent
int const * const k;

2. Array pointer

Definition method
int (*p)[10]//p is an address that points to an integer array of 10 elements
//Pointer array
int *p[10]//Ten elements in p are of type int*
//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, pointing to an array, called array pointer.
//Note here that the priority of [] is higher than that of *, so () must be added to ensure that p is combined with * first

As the name suggests, the pointer to the array. As we all know, the array name is the address of the first element of the array, and the array pointer certainly points to the first element of the array. What's the difference between an array name and an array pointer

Note: & array name takes out the address of the whole array. Different from the first element of the array, array name + 1 advances one element, but & array name + 1 skips the whole array

Pointer arrays are often used for two-dimensional arrays

void print_arr(int (*arr)[5], int row, int col)
{
int i = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
printf("%d ", arr[i][j]);//arr[i] = *(arr+1) arr[i][j] = *(*(arr+i)+j)
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
//The array name arr represents the address of the first element
//But the first element of the two-dimensional array is the first row of the two-dimensional array
//So the arr passed here is actually equivalent to the address of the first line, which is the address of a one-dimensional array
//You can use array pointers to receive
print_arr(arr, 3, 5);
return 0;
}

Array parameters

One dimensional array

void test(int arr[])
{}
void test(int arr[10])//For the convenience of beginners, it can be introduced in this way during design
{}
void test(int* arr)//The array name should be the first element address, and it is reasonable to receive it with a pointer
{}
void test2(int* arr[20])
{}
void test2(int** arr)//arr2 is originally a pointer, and the pointer is received with a secondary pointer
{}
int main()
{
	int arr[10] = { 0 };
	int* arr2[20] = { 0 };
	test(arr);
	test2(arr2);
}

Two dimensional array

void test(int arr[3][5])
{}
void test(int arr[][5])//Different here, others can be compared with one-dimensional arrays
{}
//For two-dimensional array parameters, the design of function parameters can only omit the first [] number.
//Because for a two-dimensional array, you can't know how many rows there are, but you must know how many elements there are in a row.
//This is convenient for calculation.
void test(int* arr)
{}
void test(int* arr[5])
{}
void test(int(*arr)[5])//The first row of pointers can be used to simulate a two-dimensional array
{}
void test(int** arr)
{}
int main()
{
	int arr[3][5] = { 0 };
	test(arr);
}

Primary pointer

#include <stdio.h>
void print(int* p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d\n", *(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]);
	//First level pointer p, passed to function
	print(p, sz);
	return 0;
}

Function pointer

void (*p)(int,float)//It can be compared with array pointers. p is first combined with * and then there is a function call operator, that is, p points to a function as a pointer, and the function type is void(int, float)

There are many dolly operations related to function pointers, which are not the focus of this article. I'll take them with me
Function pointer array

int  (*p[10])();

The array contains 10 function pointers

Pointer corresponding to function pointer array

void(*(*p)[5])(int)

a key

2, Analysis of pointer and array written test questions

Two exceptions to array names
The array name is the address of the first element of the array, and the separate & array name and sizeof (array name) are the address of the array

Bedding

1. One dimensional array

int main() 
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//The array name a is placed separately in sizeof. The size of the entire array is calculated in bytes, 4 * 4 = 16
	printf("%d\n", sizeof(a + 0));//a represents the address of the first element of the array. a+0 is also the address of the first element of the array. The address size is 4 / 8
	printf("%d\n", sizeof(*a));//A represents the address of the first element, * a is the dereference of the address of the first element, which is the first element, and the size is 4 bytes
	printf("%d\n", sizeof(a + 1));//A represents the address of the first element, a+1 is the address of the second element, is the address, and the size is 4 / 8 bytes
	printf("%d\n", sizeof(a[1]));//a[1] is the second element of the array, with a size of 4 bytes
	printf("%d\n", sizeof(&a)); //&A indicates the address of the array. The address of the array is also an address. The address size is 4 / 8 bytes
	printf("%d\n", sizeof(*&a));//It can be understood as the * and & offset effect, * & A is equivalent to a,sizeof(a) is 16 & A - > int(*)[4] & A is the address of the array, and its type is int(*)[4] array pointer. If you dereference, you will access an array of 4 ints, with a size of 16 bytes
	printf("%d\n", sizeof(&a + 1));//&A is the address of the array, & A + 1 is the address after skipping the entire array, which is 4 / 8
	printf("%d\n", sizeof(&a[0]));//&A [0] get the address of the first element of the array. The address is 4 / 8
	printf("%d\n", sizeof(&a[0] + 1));//&A [0] + 1 is the address of the second element. The address size is 4 / 8 bytes

	return 0;
}

sizeof Only focus on the size of occupied space, in bytes
/sizeof Do not pay attention to type
sizeof Is operator

strlen

#include <string.h>
//strlen calculates the number of characters before \ 0 in the string of interest
//strlen is only for strings
//strlen is a library function

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", strlen(arr));//arr is the address of the first element, but there is no \ 0 in the arr array. When calculating, you don't know when to stop. The result is: random value
	printf("%d\n", strlen(arr + 0));//arr is the address of the first element. arr+0 is also the address of the first element. The result is: random value
	printf("%d\n", strlen(*arr)); //err,strlen needs an address. Start from this address and look for characters backward until \ 0,
	//Count the number of characters. But * arr is the first element of the array, that is, 'a'. This is the ascii code value 97 of 'a' passed to strlen,
	//The strlen function will take 97 as the starting address and count the string, which will form a memory access conflict
	
	printf("%d\n", strlen(arr[1]));//err as in the previous one, memory access conflicts

	printf("%d\n", strlen(&arr));//&arr is the address of the arr array. Although the type is different from the parameter type of strlen,
	//However, after the parameter is passed, the number character is still backward from the position of the first character, and the result is still a random value.

	printf("%d\n", strlen(&arr + 1));//Random value
	printf("%d\n", strlen(&arr[0] + 1));//Random value

	printf("%d\n", sizeof(arr));//As an array list, arr is placed inside sizeof. The size of the entire array is calculated in bytes, 6
	printf("%d\n", sizeof(arr + 0));//arr is the address of the first element. arr+0 is also the address of the first element. The address size is 4 / 8
	printf("%d\n", sizeof(*arr));//Arr is the address of the first element, * arr is the first element, which is a character, the size is a byte, 1
	printf("%d\n", sizeof(arr[1]));//arr[1] is the second element of the array. It is a character with a size of 1 byte
	printf("%d\n", sizeof(&arr));//&Arr takes out the address of the array. The address of the array is also the address. The address is 4 / 8 bytes
	printf("%d\n", sizeof(&arr + 1));//&Arr takes out the address of the array, & arr + 1, skipping the whole array, & arr + 1 is still the address, and the address is 4 / 8 bytes
	printf("%d\n", sizeof(&arr[0] + 1));//&Arr [0] is the address of the first element, & arr [0] + 1 is the address of the second element, and the address is 4 / 8 bytes
	return 0;
}
#include <stdio.h>
#include <string.h>
int main()
{
		char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//Hide \ 0 after "abcdef". strlen calculates the number of characters before \ 0. The result is 6
	printf("%d\n", strlen(arr + 0));//Arr is the address of the first element of the string, arr+0 is still, and the result is+
	printf("%d\n", strlen(*arr));//Arr is the address of the first element of the array, * arr is' a ', the ASCII code of a is 97, and strlen will address \ 0 backward with 97 as the address, resulting in memory access conflict
	printf("%d\n", strlen(arr[1]));//arr[1] is the same as above, forming a memory access conflict
	printf("%d\n", strlen(&arr));//&Arr retrieves the address of the entire array. The data is still the same as the address of the first element of the array, but after passing in strlen, it still looks back in characters \ 0; Or random value
	printf("%d\n", strlen(&arr + 1));//The address after the array \ 0 is passed in. Look back for \ 0, or a random value
	printf("%d\n", strlen(&arr[0] + 1));//Passed in the address of b, 5

	printf("%d\n", sizeof(arr));//arr in sizeof exists alone, indicating the entire array, 6
	printf("%d\n", sizeof(arr + 0));//arr+0 is the first element of the array, 1
	printf("%d\n", sizeof(*arr));//Arr is the address of the first element of the array, * arr is a, 1
	printf("%d\n", sizeof(arr[1]));//It's' b ', 1
	printf("%d\n", sizeof(&arr));//&Arr is a pointer variable even if it is the address of the entire array, 4 / 8
	printf("%d\n", sizeof(&arr + 1));//Pointer variable, 4 / 8
	printf("%d\n", sizeof(&arr[0] + 1));//Pointer variable, 4 / 8
	return 0;
}
int main()
{
	char* p = "abcdef";
		
	printf("%d\n", strlen(p));//p stores the address of 'a'. strlen(p) is to find the length of the string from the position of 'a', and the length is 6
	printf("%d\n", strlen(p + 1));//p+1 is the address of 'b'. Starting from the position of b, the length of the string is 5
	printf("%d\n", strlen(*p));//'a',err
	printf("%d\n", strlen(p[0]));//err
	printf("%d\n", strlen(&p));//Take out another address, random value
	printf("%d\n", strlen(&p + 1));//Ditto, random value
	printf("%d\n", strlen(&p[0] + 1));//P [0] - > * (P + 0) - > * P - > 'a', & P [0] is the address of the first character, and & P [0] + 1 is the address of the second character
	//A numeric character string from the position of the second character backward, with a length of 5
		
		
	printf("%d\n", sizeof(p)); //p is a pointer variable. sizeof(p) calculates the size of the pointer variable, 4 / 8 bytes
	printf("%d\n", sizeof(p + 1));//p is a pointer variable that stores the address. p+1 is also the address. The address size is 4 / 8 bytes
	printf("%d\n", sizeof(*p));//*p accesses 1 byte
	printf("%d\n", sizeof(p[0]));//P [0] -- > * (P + 0) - > * p 1 byte
	printf("%d\n", sizeof(&p));//&P is also an address, which is 4 / 8 bytes, and & P is a secondary pointer
	printf("%d\n", sizeof(&p + 1)); //&P is the address. After + 1, it is still the address. If yes, the address is 4 / 8 bytes
	//&p + 1 is the address of p + 1, which is the address after skipping the p variable in memory
	printf("%d\n", sizeof(&p[0] + 1));//p[0] is a, & p[0] is the address of a, & p[0] + 1 is the address of b,
	//Yes, the address is 4 / 8 bytes
	return 0;

}

2. Two dimensional array


int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//The array list is placed in sizeof alone. It calculates the size of the whole array, 48
	printf("%d\n", sizeof(a[0][0]));//The size of an element is of type int, 4
	printf("%d\n", sizeof(a[0]));//a[0] represents the array name of the first row. a[0] is placed inside sizeof as an array list, and the size of the first row is calculated., sixteen
	printf("%d\n", sizeof(a[0] + 1));//a[0] is the first row of the array and exists alone, that is, the address of the second element in the first row is the pointer variable 4 / 8
	printf("%d\n", sizeof(*(a[0] + 1)));//Next, it's an element, 4
	printf("%d\n", sizeof(a + 1));//Address of the second line, pointer variable 4 / 8
	printf("%d\n", sizeof(*(a + 1)));//Connect 16
	printf("%d\n", sizeof(&a[0] + 1));//&A whole line, + 1 is the address of the second line 4 / 8
	printf("%d\n", sizeof(*(&a[0] + 1)));//The next line is 16
	printf("%d\n", sizeof(*a));//Take the first line and combine it with sizeof. sixteen
	printf("%d\n", sizeof(a[3]));//It feels crossed, but it doesn't matter, 16
	return 0;
}

3, Interview questions

int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);//Take the address after 5 and force the type to be converted to int*
printf( "%d,%d", *(a + 1), *(ptr - 1));//*(ptr-1) forward retrieved 5
return 0;
}


2.

struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//Suppose the value of p is 0x100000. What are the values of the expressions in the following table?
//It is known that the variable size of the structure Test type is 20 bytes
int main()
{
printf("%p\n", p + 0x1);//Structure type plus one, skip 20 bytes and convert hexadecimal to 14
printf("%p\n", (unsigned long)p + 0x1);//Convert to unsigned long shaping, that is, add the number 1 and print in the form of% p
printf("%p\n", (unsigned int*)p + 0x1);//Cast type to unsigned integer pointer, + 1 skipped 4, printed as% p
return 0;
}


3.

int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);//Get the address after 4 and force the type to be converted to int*
int *ptr2 = (int *)((int)a + 1);//a is the address of the first element of the array, which is converted to int type, as shown in the figure.
printf( "%x,%x", ptr1[-1], *ptr2);//Are printed in hexadecimal
return 0;
}

Take the small end byte order of vs2019 as an example
When the address is converted to int type, + 1 is the address + 1, and the number 1, that is, a byte, is converted to int *. As shown in the figure, it is also sorted by the small end. The low end is placed at the low address, the high end is placed at the high address, and 02 is the high end
02000000


4.

#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };//Pit, pit, it's a bracket, not a brace, it's a comma expression!!
//In fact, int a[3][2] = {1,3,5};
int *p;
p = a[0];//first line
printf( "%d", p[0]);//First element
return 0;
}


5.

int main()
{
int a[5][5];
int(*p)[4];//Note that only [4], drawing on draft paper, it is recommended to draw horizontally
p = a;
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//The address is subtracted by the number of elements, and the small address - large address is negative, that is - 4
return 0;
}


When printing - 4 as% p
Original code: 1000000000000000000000000 100
Inverse code 11111111111111111111111111011
Complement 11111111111111111111111111100
Convert to hex FF FC

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;



7.

#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}



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;
}

summary

The above is what I want to talk about today. This paper only briefly introduces the use of pointers, and pointers provide a powerful method for data processing. It's still more important
This article is only for the purpose of sorting out learning notes. Please correct any suggestions and mistakes

Code text is not easy, looking forward to the third consecutive

Topics: C data structure Back-end Interview linked list