当前位置:网站首页>C language pointer (exercises)
C language pointer (exercises)
2022-07-07 09:07:00 【A big cat 1201】
author : A big cat 1201
special column :《C Language learning 》
Maxim : You just try to , Leave the rest to time !
C Language pointer ( Exercises )
After the detailed explanation of pointer in the previous four articles , I believe you have learned about all kinds of pointers and how to use them , Let's do some exercises to test our learning achievements .
Pointers and arrays
One dimensional array
Exercises 1 :
#include <stdio.h>
int main()
{
int a[] = {
1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
return 0;
}
We know ,
The essence of the array name of a one-dimensional array is the address of the first element of the array .
But there are two exceptions
- & Array name
- sizeof( Array name )
In these two special cases , The array name represents the entire array .
After knowing this knowledge point, you can solve the above code , What is the output of the above code ? You can try it yourself .
Let's make a detailed analysis .
- First, create a one-dimensional array
int a[] = {
1,2,3,4 };
The array has 4 Elements , The integer of each element .
printf("%d\n", sizeof(a));
The operator sizeof The operands in only have array names , So at this time, we need to find the memory space occupied by the whole array , The result is 16, That is to say 16 Bytes .
printf("%d\n", sizeof(a + 0));
- The operand is the array name plus an integer 0, So it's not a single array name , At this point, the essence of the array name is the address of the first element of the array .
- Add one to the address of the first element 0 What you get is the address of the first element .
- The address of the first element is a int* Pointer variable of type , So the result is 4 perhaps 8, stay 32 On the bit platform is 4, stay 64 On the bit platform is 8.
printf("%d\n", sizeof(*a));
- Operand is array name dereference , Not a separate array name .
- At this point, the essence of the array name is the address of the first element of the array .
- After dereferencing the address of the first element, you get the first element in the array .
- So its size is an integer size , The result is 4.
printf("%d\n", sizeof(a + 1));
- Operands are array names plus integers 1, Not a separate array name
- At this point, the essence of the array name is the address of the first element of the array .
- Add 1 Then it becomes the address of the second element in the array , That's the element 2 The address of .
- The address is int* Pointer variable of type .
- So the size is 4 perhaps 8 Bytes (32 Bit platform is 4,64 Bit platform is 8).
printf("%d\n", sizeof(a[1]));
- The operand is an array with a subscript 1 The elements of , That is, the second element .
- Its size is 4 Bytes , So the result is 4.
printf("%d\n", sizeof(&a));
- The operands are & Array name , At this point, the address of the whole array is taken out .
- The data type of this address is int (*)[4], Is an array pointer variable type .
- In the final analysis, it is still an address , So the result is 4 perhaps 8.
printf("%d\n", sizeof(*&a));
- The operands are *&a.
- Dereference operator * And address operator & Offset each other , All that's left is the array name .
- sizeof When the operand of has only the array name , Its essence is the whole array .
- The result is 16.
printf("%d\n", sizeof(&a + 1));
- The operands are &a+1
- &a What you get is the address of the entire array , The type of the needle is int (*)[4].
- Add 1 Then skip the entire array , Points to the next in memory int (*)[4] The address of .
- In the final analysis, it is still an address , So the result is 4 perhaps 8.
printf("%d\n", sizeof(&a[0]));
- The operands are &a[0].
- a[0] The result is the first element in the array , Then take the address .
- What you get is the address of the first element of the array .
- So the result is 4 perhaps 8.
printf("%d\n", sizeof(&a[0] + 1));
- The operands are &a[0]+1.
- &[0] What you get is the address of the first element of the array .
- Add 1 What you get is the address of the second element in the array
- The data type is int* Pointer variable of type .
- So the result is 4 perhaps 8.
Combine the above analysis , Because the compiler used by benmew is 32 Bit , Annotate the results of each line of code to the end of the corresponding code
It can be seen that the output results are consistent with our analysis .
A character array
Exercises 1 :
int main()
{
char arr[] = {
'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
return 0;
}
char arr[] = {
'a','b','c','d','e','f' };
This is an array of characters , Array has 6 Elements .
printf("%d\n", sizeof(arr));
- The operand is the array name .
- At this point, the essence of the array name is the entire array .
- So the result is the size of the entire array , The result is 6.
printf("%d\n", sizeof(arr + 0));
- The operands are arr+0
- Not a single array name , At this point, the essence of the array name is the address of the first element of the array
- Add 0 After that, it is still the address of the first element of the array
- The address is char* Pointer to type
- The result is 4 perhaps 8
printf("%d\n", sizeof(*arr));
- The operands are *arr, Not a separate array name
- At this point, the essence of the array name is the address of the first element of the array
- After dereferencing, you get the first element in the array
- The data type of this element is char type
- The result is 1
printf("%d\n", sizeof(arr[1]));
- The operands are arr[1]
- The result is that the subscript in the array is 1 The elements of
- The data type of this element is char type
- The result is 1
printf("%d\n", sizeof(&arr));
- The operands are &arr, It takes out the address of the entire array
- The data type is char (*)[6], It's an array pointer
- Is it an address after all
- The result is 4 perhaps 8
printf("%d\n", sizeof(&arr + 1));
- The operands are &arr+1
- &arr It takes out the address of the entire array , Is a data type is char (*)[6] Pointer to type
- Add 1 Then skip the entire array , Point to the next char (*)[6] Address of type array
- The address of the next array is still an address in the final analysis
- The result is 4 perhaps 8
printf("%d\n", sizeof(&arr[0] + 1));
- The operands are &arr[0]+1
- &arr[0] What you get is the address of the first element of the array
- Add 1 What you get is the address of the second element in the array
- The data type is char* Pointer to type
- So the result is 4
Combine the above analysis , Because the compiler used by benmew is 32 Bit , Annotate the results of each line of code to the end of the corresponding code
It can be seen that the output results are consistent with our analysis .
Exercise 2 :
#include <string.h>
int main()
{
char arr[] = {
'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
return 0;
}
- What is used in this code is strlen() Library function to find the length of the string .
- strlen The essence of library function is to find the character end mark in the string \0
- And then \0 The number of previous characters is counted
char arr[] = {
'a','b','c','d','e','f' };
This is an array of characters , Yes 6 Elements , Every element is char Type of .
printf("%d\n", strlen(arr));
- The argument is arr, It's not a special case
- At this point, the essence of the array name is the address of the first element of the array
- Because there is no... In the array \0, therefore strlen The function cannot find the flag of the end of Statistics
- So the result is a random number , But this random number must be greater than or equal to 6
printf("%d\n", strlen(arr + 0));
- The argument is arr+0
- arr Is the address of the first element of the array , Add 0 After that, it is still the address of the first element of the array
- So the result is the same as that of the above statement code
printf("%d\n", strlen(*arr));
- The argument is *arr
- At this time arr Is the address of the first element of the array
- After dereferencing, you get the first element in the array , That's the character ’a’
- The character a Send it as an address to strlen Library function
- Because the characters a Of ASCII The code value is 97, So it's equivalent to passing a char* Pointer to type , Its value is 97
- The address is 97 The memory space of is used by the kernel , The user does not have access , So the compiler will report an error .
- Decimal system 97 Turn it into 16 After the decimal is 61
- The error content tells us the access address 0x00000061 Error in time
- That is to say, we are not allowed to access this memory space
printf("%d\n", strlen(arr[1]));
- The argument is arr[1]
- What you get is the second element in the array , That is to say ’b’
- character b Of ASCII The code value is 98, Turn it into 16 Hexadecimal followed by 62
- Same as the code above , The same is true of 62 As an address to strlen Library function
- and 0x00000062 The memory space of is also inaccessible , You will also report mistakes.
printf("%d\n", strlen(&arr));
- The argument is &arr, It is a case in a special case
- It takes out the address of the entire array
- But the address expression of the whole array is the address of the first element of the array , Its value and arr equally
- although &arr The data type of is char (* )[6], But it's passing to strlen The library function will be forcibly converted to cahr* Pointer to type
- So the result is also a random value , Result greater than or equal to 6, The result is the same as the first input statement .
printf("%d\n", strlen(&arr + 1));
- The argument is &arr+1
- &arr It takes out the address of the entire array
- Add one and skip the array , Point to the next char (*)[6] Address of type array
- Because I don't know the distribution of elements in the pointing array at this time , So the result is a random value .
printf("%d\n", strlen(&arr[0] + 1));
- The argument is &arr[0]+1
- &arr[0] What you get is the address of the first element of the array
- Add 1 What you get is the address of the second element of the array
- Send this address to strlen After library function , Because there is no \0, So I still don't know where to end the statistics
- But this random value must be a smaller number than the random value above .
Combine the above analysis , Annotate the results of each line of code to the end of the corresponding code
The results are consistent with our analysis .
The code will report some warnings during pointing , Let's just ignore it , Interested friends can try to repair it .
Exercise 3 :
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
return 0;
}
char arr[] = "abcdef";
This is an array of strings , Array has 7 Elements , Every element is char type .
amount to
char arr[] = {
'a','b','c','d','e','f','\0' };
printf("%d\n", sizeof(arr));
- The operands are arr, There is only one array name
- here arr The essence of is the whole array
- So the result is 7
printf("%d\n", sizeof(arr + 0));
- The operands are arr+0, Not a single array name
- here arr The essence of is the address of the first element of the array
- Add 0 After that, it is still the address of the first element of the array
- The address is char* Pointer to type
- So the result is 4 perhaps 8
printf("%d\n", sizeof(*arr));
- The operands are *arr, Not a separate array name
- here arr The essence of is the address of the first element of the array
- After dereferencing, you get the first element in the array
- So the result is 1
printf("%d\n", sizeof(arr[1]));
- The operands are arr[1]
- The result is that the subscript in the array is 1 The elements of , That is, the second element
- So the result is 1
printf("%d\n", sizeof(&arr));
- The operands are &arr, It takes out the address of the entire array
- The address is a char (*)[7] Pointer to type
- In the final analysis, it is still a pointer
- So the result is 4 perhaps 8
printf("%d\n", sizeof(&arr + 1));
- The operands are &arr+1
- &arr It takes out the address of the entire array
- Add 1 After skipping the array , Point to next char (*)[7] The address of
- At this time, the address is still a pointer
- So the result is 4 perhaps 8
printf("%d\n", sizeof(&arr[0] + 1));
- The operands are &arr[0]+1
- &arr[0] What you get is the address of the first element of the array
- Add 1 What you get is the address of the second element in the array
- The data type of this address is char*
- So the result is 4 perhaps 8
Combine the above analysis , Because the compiler used by benmew is 32 Bit , Annotate the results of each line of code to the end of the corresponding code
You can see , It is consistent with the results of our analysis .
Exercise 4 :
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
return 0;
}
char arr[] = "abcdef";
This is an array , Yes 7 Elements , Every element is char type .
printf("%d\n", strlen(arr));
- The argument is arr
- At this time arr The essence of is the address of the first element of the array
- take arr Pass the reference to strlen After library function , Start counting the number of characters here , until \0 End the statistics
- So the result is the number of characters , But not including \0
- So the result is 6
printf("%d\n", strlen(arr + 0));
- The argument is arr+0
- here arr The essence of is the address of the first element of the array
- Add 0 After that, it is still the address of the first element of the array
- So the result is the same as that of the above statement , It's also 6
printf("%d\n", strlen(*arr));
- The argument is *arr
- here arr The essence of is the address of the first element of the array
- After dereferencing, you get the first element in the array , That is to say ’a’
- character a Of ASCII The code value is 97
- At this time, the address is 97 Pass a pointer to the class strlen Library function
- The address is converted to 16 Hexadecimal followed by 0x00000061
- This address is not accessible , Therefore, an error will be reported during execution
- The specific results are the same as those reported in the previous exercises
printf("%d\n", strlen(arr[1]));
- The argument is arr[1]
- What you get is the second element in the array , That is to say ’b’
- character b Of ASCII The code value is 98
- The same is equivalent to the address 98, That is to say 0x00000062 Pass the parameter to strlen
- Errors will also be reported during execution
printf("%d\n", strlen(&arr));
- The argument is &arrr, It takes out the address of the entire array
- At this time, the data type of the argument is char (*)[7]
- Pass a pointer of this type to strlen The library function will be cast to char* Pointer to type
- Although it is the address of the whole array , But its value is the same as the address of the first element of the array
- So also from the character a Start counting the number of characters , Until I met \0
- So the result is 6
printf("%d\n", strlen(&arr + 1));
- The argument is &arr+1
- &arr It takes out the address of the entire array
- Add 1 After skipping the array , Point to the next char (*)[7] Type of address
- Because I don't know the distribution of elements behind the array
- So the result is a random value
printf("%d\n", strlen(&arr[0] + 1));
- The argument is &arr[0]+1
- &arr[0] What is taken out is the address of the first element of the array
- Add 1 The result is the address of the second element in the array
- Send this address to strlen After library function
- Count the number of characters from the second element , until \0 end
- So the result is 5
Combine the above analysis , Annotate the results of each line of code to the end of the corresponding code
You can see , It is consistent with the results of our analysis .
Exercise five :
int main()
{
char* p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p + 1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p + 1));
printf("%d\n", sizeof(&p[0] + 1));
return 0;
}
char* p = "abcdef";
- The string exists in the constant area of memory , They also have addresses
- This statement converts the characters in the string a The address character of gives the pointer variable p
printf("%d\n", sizeof(p));
- The operands are p
- p Is a pointer variable
- The essence of which is sizeof(char*)
- So the result is 4 perhaps 8
printf("%d\n", sizeof(p + 1));
- The operands are p+1
- Now the variable p The value in is the character b The address of
- So the result is 4 perhaps 8
printf("%d\n", sizeof(*p));
- The operands are *p
- p The value in is the character a The address of
- After dereferencing, you get a character a
- So the result is 1
printf("%d\n", sizeof(p[0]));
- The operands are p[0]
- p[0] It can be written. *(p+0)
- p The value in is the character a The address of
- Add 0 It's still a The address of
- After dereferencing, you get the character a
- So the result is 1
printf("%d\n", sizeof(&p));
- The operands are &p
- The data type is char** A secondary pointer to
- In the final analysis, it is still a pointer
- So the result is 4 perhaps 8
printf("%d\n", sizeof(&p + 1));
- The operands are &p+1
- &p What you get is a secondary pointer
- Add 1 After that, add to the secondary pointer 1, But it is still a pointer
- So the result is 4 perhaps 8
printf("%d\n", sizeof(&p[0] + 1));
- The operands are &p[0]+1
- p[0] It can be written. *(p+0)
- p The value in is the character a The address of
- Add 0 There are still characters after a The address of
- After dereferencing, you get characters a
- Check the characters again a Address fetch , What you get is characters a The address of
- add 1 What you get is characters b The address of
- It's still an address
- So the result is 4 perhaps 8
Combine the above analysis , Because the compiler used by benmew is 32 Bit , Annotate the results of each line of code to the end of the corresponding code
Exercise 6 :
int main()
{
char* p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p + 1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p + 1));
printf("%d\n", strlen(&p[0] + 1));
return 0;
}
char* p = "abcdef";
It is also the character a The address of is assigned to the pointer variable p.
printf("%d\n", strlen(p));
- The argument is p, The value put is a character a The address of
- Pass the reference to strlen After the library function, the number of characters will be counted backwards , until \0 end , But not including \0
- So the result is 6
printf("%d\n", strlen(p + 1));
- The argument is p+1
- p The value in is the character a The address of
- Add 1 Then it becomes a character b The address of
- Pass the reference to strlen After the library function, the character b Start counting the number of characters , until \0 end
- So the result is 5
printf("%d\n", strlen(*p));
- The argument is *p
- p The middle is a character a The address of
- After dereferencing, you get characters a
- character a Of ASCII The code value is 97, convert to 16 Hexadecimal followed by 61
- It is equivalent to putting characters a Send it as an address to strlen Library function , That is to say 0x00000061
- And the address is not allowed to be accessed by users
- Therefore, the compilation result will report an error
printf("%d\n", strlen(p[0]));
- The argument is p[0]
- It can be written. *(p+0)
- p Characters are placed in a The address of
- Add 0 There are still characters after a The address of
- After dereferencing, you get characters a
- So the result is the same as the output statement above , You will also report mistakes.
printf("%d\n", strlen(&p));
- The argument is &p
- p Characters are placed in a The address of
- After taking the address, you get a variable of type char** Second level pointer of
- The red box is the storage space of the string
- The blue square is the pointer variable p, Its value is character a The address of , Suppose it is 0x0012ff40
- The green square is &p, That is, the secondary pointer variable , Its value is the first level pointer variable p The address of , The assumption is 0x0034ff23
The compiler used by benmew is 32 Bit , And it is stored in small end byte order- p A variable is a first-order pointer variable , Its size is 4 Bytes , There are characters in it a The address of
- p The address stored in memory looks like the blue box in the above figure
- &p What you get is a pointer variable p The address of , The value of the address and the pointer variable p The address of the low byte order byte in the four bytes in the middle is the same
- Send this address to strlen The library function is then coerced into char* Type of address
- So every time 1 Skip back only one byte
- Therefore, the pointer variable will be counted again p The value in is also regarded as character statistics , Such as 40,ff,12, When you meet 00 The statistics are over
- So the output is a random value
printf("%d\n", strlen(&p + 1));
- The argument is &p+1
- &p It's the same as up here , What you get is a secondary pointer
- And add 1 Then a second level pointer type will be skipped , That is, skip four bytes
- At this time, the secondary pointer is stored in the next memory space
- Pass the secondary pointer to strlen After library function , From then on, count the number of characters
- Because I don't know where to stop , So the result is a random value
printf("%d\n", strlen(&p[0] + 1));
- The argument is &p[0]+1
- p[0] It can be written. *(p+0)
- p Characters are placed in a The address of
- Add 0 It's still a The address of
- After dereferencing, you get characters a
- Check the characters again a Take the address and add 1
- What you get is characters b The address of
- Send this address to strlen After the library function, it starts to count the number of characters backwards , until \0 end
- So the result is 5
Be careful
- There is no necessary connection between the last two random values , It's all random .
Combine the above analysis , Because the compiler used by benmew is 32 Bit , Annotate the results of each line of code to the end of the corresponding code
You can see , The results obtained are consistent with our analysis .
Two dimensional array
Exercises 1 :
int main()
{
int a[3][4] = {
0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));
return 0;
}
int a[3][4] = {
0 };
This is a two-dimensional array with three rows and four columns , Initialize all to 0, The type of each element is an integer
printf("%d\n", sizeof(a));
- The operands are a, Separate array names
- At this point, the essence of the array name is the entire array
- So the result is the memory space occupied by the entire array
- The result is 48
printf("%d\n", sizeof(a[0][0]));
- The operands are a[0][0]
- Get is the first 0 Xing di 0 The elements of the column
- So the result is 4
printf("%d\n", sizeof(a[0]));
- The operands are a[0]
- a[0] Only row labels but no column labels
- A two-dimensional array can be regarded as a one-dimensional array in which each element is a one-dimensional array
- a[0] It represents the array name of the first row of array
- Because there is only a single array name , So it represents the whole first row array
- So the result is 16
printf("%d\n", sizeof(a[0] + 1));
- The operands are a[0]+1
- a[0] Represents the array name of the first row of one-dimensional array , And not a separate array name
- a[0] The essence of is the address of the first element of the first row array
- Add 1 What you get is the address of the second element of the first array , That is to say a[0][1] Address of element
- It is a int* Pointer variable of type
- So the result is 4 perhaps 8
printf("%d\n", sizeof(*(a[0] + 1)));
- The operands are *(a[0]+1)
- According to the analysis of the above sentence, we know a[0] +1 What you get is the second 0 Xing di 1 The address of the element of the column
- After dereferencing, you get a[0][1]
- So the result is 4
printf("%d\n", sizeof(a + 1));
- The operands are a+1
- The essence of the array name of a two-dimensional array is the address of the first element
- here a It's an array pointer , The type is int (*)[4]
- Add 1 Then it points to the second line of elements
- Its type is still int (*)[4]
- In the final analysis, it is still an address
- So the result is 4 perhaps 8
printf("%d\n", sizeof(*(a + 1)));
- The operands are *(a+1)
- From the analysis of the above sentence, we know a+1 What you get is the address of the element in the second line
- After dereferencing it, you get the second row of the entire one-dimensional array
- So the result is the size of the second row of one-dimensional array
- The result is 16
printf("%d\n", sizeof(&a[0] + 1));
- The operands are &a[0]+1
- a[0] Is the array name of the first row of one-dimensional array
- Take its address &a[0] What you get is the address of the first row of the one-dimensional array , The type is int (*)[4]
- add 1 What you get is the address of the second row of one-dimensional array , It is also an array pointer
- In the final analysis, it is still a pointer
- So the result is 4 perhaps 8
printf("%d\n", sizeof(*(&a[0] + 1)));
- The operands are *(&a[0]+1)
- According to the above analysis, we know &a[0]+1 What you get is the address of the entire one-dimensional array in the second line
- After dereferencing, you get the whole one-dimensional array in the second row
- So the result is the memory space occupied by the second row of data
- The result is 16
printf("%d\n", sizeof(*a));
- The operands are *a, Not a separate array name
- In this case, the array name a The essence of is the address of the first element of the array , It's a int (*)[4] Pointer to type
- Dereference the address of the first line element to get the first line element
- So the result is 16
printf("%d\n", sizeof(a[3]));
- The operands are a[3]
- a[3] Represents the array name of the fourth row of one-dimensional array
- Because the array in the code is 3 That's ok 4 Column , So here's the first 4 The line has crossed the line to visit
- Although the array is out of bounds , But the row pointing to the outside of the array is also a 4 One dimensional array of columns
- At this time, it is equivalent to that only the array list appears
- So the result is 16
Combine the above analysis , Because the compiler used by benmew is 32 Bit , Annotate the results of each line of code to the end of the corresponding code
You can see , The results are consistent with our analysis .
Pointer written test questions
- Pen test 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;
}
- In the green box is an array a Distribution in memory
- Array name a Is the address of the first element of the array , That's the element 1 The address of
- &a What you get is the address of the entire array , It's a int (*)[5] Array pointer to
- &a+1 Skipped the entire array a, Points to another array of the same size later
- Cast the array pointer at this time into int* The pointer to , And assign it to the pointer variable ptr
- here ptr-1 Moved one to the left int type , That is to say 4 Bytes , Points to the element 5 The address of
- a The essence of is the address of the first element of the array
- Add 1 What you get is the address of the second element in the array , That's the element 2 The address of
printf("%d,%d", *(a + 1), *(ptr - 1));
- Yes a+1 Dereference results in elements 2
- Yes ptr-1 Dereference results in elements 5
- So the result is 2,5
Consistent with our analysis .
- Pen test 2:
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p = 0x10000000;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
- Created a structure , With 32 For example, a bit machine , The memory space occupied by this structure is 20 Bytes
- Use a structure pointer variable to point to the structure , At this time, the pointer variable p In the middle is the address of the structure
printf("%p\n", p + 0x1);
- p In the middle is the address of the structure ,0x10000000
- Add 0x1 The latter is equivalent to adding 1, Skip the whole structure , That is to say, add 20
- convert to 16 The result is 0x10000014
printf("%p\n", (unsigned long)p + 0x1);
- Put the pointer variable p Cast bit unsigned long type
- here p The value in is no longer the address of the structure , But an unsigned long integer number
- Add 0x1 after , That is to say, add 1 after , Is doing arithmetic operations
- So the result is 0x10000001
printf("%p\n", (unsigned int*)p + 0x1);
- Put the pointer variable p Cast bit unsigned int* type
- here p The value in is no longer the address of the structure , It is a unsgined int* Pointer variable of type , Its value is a point unsigned int Address of type data .
- Add 0x1 after , That is to say, add 1 after , Skip is a unsigned int Data of type , That is to say 4 Bytes
- So the result is 0x10000004
You can see , It is consistent with the results of our analysis .
A warning will be given during operation , But it does not affect the output of our results .
- Pen test 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;
}
- With VS2019 For example
- Store data in small byte order
- yes 32 Bit platform
- Pictured above , Array name a The essence of is the address of the first element of the array , Points to the address of the first element
- And because it is stored in small byte order , So the address of the first element is the lowest byte in the first element 01 The address of
int* ptr1 = (int*)(&a + 1);
- Original a The data type of is int* Pointer to type , Cast bit integer , At this point, its meaning is no longer a pointer , It's a number
- Add 1 Later, we are doing arithmetic operations , Its value increases 1
- Cast the result to int* Pointer variable of type
- At this time, the pointer points to the address of the second low byte order byte in the four bytes of the first element , As shown in the figure above 00
- Assign this address to the pointer variable ptr2
int* ptr1 = (int*)(&a + 1);
- &a Get the address of the entire array
- Add 1 Then skip the whole array , At this point, the pointer points to the next int (*)[4] Type of address
- Cast the pointer to int* Type is assigned to the pointer variable ptr1
printf("%x,%x", ptr1[-1], *ptr2);
- ptr1[-1] It can be written. *(ptr1-1)
- ptr1-1 The resulting value points to the last element in the array 4 The address of
- After dereferencing, get the element 4
- ptr2 After dereferencing, we get from ptr2 Start later 4 It's made up of two bytes int Data of type
- Because it is a small end byte order storage mode
- So after you go out, you should int The type of data is 02 00 00 00
- according to 16 Binary printing
- So the result is 2000000
- So the end result is 4,2000000
It can be seen that the results are consistent with our analysis .
- Pen test 4:
#include <stdio.h>
int main()
{
int a[3][2] = {
(0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
int a[3][2] = {
(0, 1), (2, 3), (4, 5) };
- This is a two-dimensional array with three rows and two columns , And it is not completely initialized , The type of each element is int type
- The contents in braces are comma expressions
- { (0, 1), (2, 3), (4, 5) } Finally, the initial value of the two-dimensional array is 1,3,5
- The element in the first line is 1,3
- The element of the second line is 5,0
- The element in the third line is 0,0
- At this time a[0] The essence of is the array name of the first row of one-dimensional array , That is the first. 0 Xing di 0 The address of the column element
- Assign this address to the pointer variable p
printf("%d", p[0]);
- p[0] It can be written. *(p+0)
- p The value in is a[0][0] The address of
- Add 0 After that, it is still the address of the element
- After dereferencing, you get this element
- So the result is 1
You can see , The results are consistent with our analysis .
- Pen test 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;
}
We know , Two dimensional arrays are also stored continuously in memory
- The above figure shows the distribution of two-dimensional arrays in memory
int(*p)[4]; p = a;
- Here we create an array pointer , But the array that this pointer points to is 4 An element of , The type of each element is int Type of
- And the array name a The data type of is int (*)[5] Of
- take a The pointer represented by is forcibly assigned to the array pointer p
- Now stand in p From the perspective of , It's just one with 4 A pointer to an array of elements
- p+1 Will skip a 4 One dimensional array of elements , Point to the original 5 Of the last element of an array of elements , As shown in the figure above p+1
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
- analysis &p[4][2] - &a[4][2]
- p[4][2] It can be written. *(*(p+4)+2)
- p In the middle is the first 4 The address of an array of elements
- Add 4 Then it points to the 4 individual 4 One dimensional array of elements , As shown in the figure above p+4 The point is
- Yes p+4 After dereferencing, the result is 4 individual 4 One dimensional array of elements , That is, the array name of this array
- Because only the array name can represent an array
- The essence of an array name is the address of the first element of the array , therefore *(p+2) Is the address of the first element of the array
- *(p+4)+2 Points to the... In the array 3 Elements
- Then dereference the address to get the element
- Then take the address of the element to get its address , As the green box in the above figure points to the space
- &a[4][2] Getting is the first 4 Xing di 2 The address of the element of the column , As the space pointed by the black box in the above figure
- And because the address minus the address gets the number of elements between the two addresses
- &p[4][2] The value is less than &a[4][2] Value
- &p[4][2] - &a[4][2] The result is -4
- -4 The complement in existence is 111111111111111111111111111100
- according to %p Print , What you print out is what the number in memory looks like , yes FFFFFFFC
- according to %d Print , What is printed out is its complement , yes -4
You can see , It is consistent with the results of our analysis .
- Pen test 6:
int main()
{
int a[2][5] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)(*(a + 1));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
- The distribution of array elements is shown in the figure above
- &a Medium a Represents the entire array
- &a+1 Skip the entire two-dimensional array , Point to the next two-dimensional array , As shown in figure of &a+1 Position shown
- At this time, the address is forcibly converted to int* Pointer to type , Assign a value to ptr1
- Array name a It represents the address of the first element of the two-dimensional array
- a+1 The next point is the address of the element in the second row of the two-dimensional array
- Cast type to int* Pointer to type , Assign a value to ptr2
- here ,ptr1-1 It points to numbers 10 The space ,ptr2-1 It points to numbers 5 Point to space
- The results obtained after dereferencing are 10 and 5
You can see , It is consistent with the results of our analysis .
- Pen test 7:
#include <stdio.h>
int main()
{
char* a[] = {
"work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
- 3 Strings are stored in the constant area , As shown in the red box in the figure
- Created a pointer array , The array has 3 Elements , The type of each element is char* type
- take 3 The addresses of the first characters of each string are placed in the pointer array a in , As shown in the blue box
- Create a secondary pointer variable pa
- Now the array a The array name of is the address of the first element of the array , Its type is a secondary pointer
- Assign the address of the first element of the array to pa
- pa++ Yes, it will pa Add... To the value in 1, here pa The value in is the address of the second element in the array
- Yes pa Dereference to get the second element in the array , This element is the address of the first character of the second string
- Print the string from here
- So the print result is at
You can see , Consistent with our analysis .
- Pen test 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;
}
- Four strings are stored in the constant area , As shown in the red box above
- Create a first level pointer array c
- Put the address of the first element of the four strings into the array in turn c in , As shown in the blue box above
- Create a second level pointer array cp
- Put the... Of the first level pointer array 4 The addresses of the elements are put into the secondary pointer array in reverse order cp in , As shown in the green box above
- Then create a three-level pointer variable pp
- Array the secondary pointer cp The address of the first element of is assigned to the three-level pointer variable cpp, As shown in the black box above
printf("%s\n", **++cpp);
- ++cpp after , Three level pointer variable cpp The value in becomes cp+1
- cp+1 Is a secondary pointer array cp The address of the second element of
- The first dereference is to address cp+1 Quoting , What we got was c+2
- c+2 Is a first-order pointer array c The address of the third element of
- The second dereference is equivalent to the address c+2 Quoting , The result is a string POINT The address of the first character
- So the result of printing is a string POINT
printf("%s\n", *-- * ++cpp + 3);
- ++cpp after , Three level pointer variable cpp The value in becomes cp+2
- cp+2 Is a secondary pointer array cp The address of the third element of
- Dereference is to address cp+2 Quoting , What we got was c+1
- c+1 Is a first-order pointer array c The address of the second element of
- Then carry out self subtraction 1 after , Will be c+1 reduce 1, Get is c
- c Is a first-order pointer array c The first element of
- Another dereference is to address c To dereference , What you get is a string ENTER The address of the first character
- Then add the address 3, What you get is a string ENTER In the character E The address of
- So the print result is ER
printf("%s\n", *cpp[-2] + 3);
- cpp[-2] It can be written. *(cpp-2)
- cpp-2 Equivalent to cp+2-2, And what you get is cp
- cp Is a secondary pointer array cp The first address in the element
- Dereference is to address cp Quoting , And what you get is c+3
- Again, dereference is to address c+3 Quoting , The result is a string FIRST The address of the first character
- add 3 The result is a string FIRST In the character S The address of
- So the print result is ST
printf("%s\n", cpp[-1][-1] + 1);
- cpp[-1][-1] It can be written. *(*(cpp-1)-1)
- here cpp The value in is still cp+2, Because only self increment can change its value
- cpp-1 Equivalent to cp+2-1, The result is cp+1
- Yes cp+1 To dereference , And what you get is c+2
- c+2 It's a one-dimensional array c The address of the third element in
- And then c+2-1 And what you get is c+1
- Yes c+1 The result of dereference is a string NEW The address of the first character
- Then add 1, What you get is a string NEW In the character W The address of
- So the print result is EW
You can see , It is consistent with the results of our analysis .
边栏推荐
- 实现自定义内存分配器
- 2022-06-30 unity core 8 - model import
- Full link voltage test of the e-commerce campaign Guide
- Digital triangle model acwing 1027 Grid access
- NVIC中断优先级管理
- 【Istio Network CRD VirtualService、Envoyfilter】
- Screen automatically generates database documents
- PMP experience learning and sharing process
- Unity Shader入门精要初级篇(一)-- 基础光照笔记
- How can I apply for a PMP certificate?
猜你喜欢
Platformization, a fulcrum of strong chain complementing chain
Lenovo hybrid cloud Lenovo xcloud: 4 major product lines +it service portal
JVM 垃圾回收 详细学习笔记(二)
C语言指针(中篇)
[istio introduction, architecture, components]
Two schemes of unit test
STM32 serial port register library function configuration method
Interview question: general layout and wiring principles of high-speed PCB
How to pass the PMP Exam in a short time?
MySQL主从延迟的解决方案
随机推荐
使用Typora编辑markdown上传CSDN时图片大小调整麻烦问题
Test pits - what test points should be paid attention to when adding fields to existing interfaces (or database tables)?
Output all composite numbers between 6 and 1000
Simulation volume leetcode [general] 1705 The maximum number of apples to eat
PMP Exam Preparation experience systematically improve project management knowledge through learning
为不同类型设备构建应用的三大更新 | 2022 I/O 重点回顾
硬件大熊原创合集(2022/05更新)
Golang etcdv3 reports an error. The attribute in grpc does not exist
The longest ascending subsequence model acwing 1017 Strange thief Kidd's glider
Esp32-ulp coprocessor low power mode RTC GPIO interrupt wake up
Upgrade Alibaba cloud RDS (relational database service) instance to com mysql. jdbc. exceptions. Troubleshooting of jdbc4.communicationsexception
Goldbach conjecture C language
个人力扣题目分类记录
模拟卷Leetcode【普通】1567. 乘积为正数的最长子数组长度
[chaosblade: node CPU load, node network delay, node network packet loss, node domain name access exception]
面试题:高速PCB一般布局、布线原则
串口实验——简单数据收发
JVM 垃圾回收 详细学习笔记(二)
徽商期货公司评级是多少?开户安全吗?我想开户,可以吗?
硬件大熊原创合集(2022/06更新)