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