当前位置:网站首页>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 .
边栏推荐
- go mod module declares its path as: gtihub. com/xxx-xx but was required as:xx-xx
- C语言指针(下篇)
- What are the conditions for applying for NPDP?
- OpenGL frame buffer
- 2022-06-30 Unity核心8——模型导入
- Summary of PMP learning materials
- Goldbach conjecture C language
- Original collection of hardware bear (updated on May 2022)
- Several common database connection methods
- 【ChaosBlade:节点 CPU 负载、节点网络延迟、节点网络丢包、节点域名访问异常】
猜你喜欢
Esp32-ulp coprocessor low power mode RTC GPIO interrupt wake up
The longest ascending subsequence model acwing 1017 Strange thief Kidd's glider
Upgrade Alibaba cloud RDS (relational database service) instance to com mysql. jdbc. exceptions. Troubleshooting of jdbc4.communicationsexception
H3C vxlan configuration
On December 8th, 2020, the memory of marketing MRC application suddenly increased, resulting in system oom
C语言指针(上篇)
Do you have any certificates with high gold content?
2020 year end summary
PPT模板、素材下载网站(纯干货,建议收藏)
Digital triangle model acwing 1027 Grid access
随机推荐
2022-07-06 Unity核心9——3D动画
硬核分享:硬件工程师常用工具包
PPT模板、素材下载网站(纯干货,建议收藏)
Esp32-ulp coprocessor low power mode RTC GPIO interrupt wake up
How long does the PMP usually need to prepare for the exam in advance?
个人力扣题目分类记录
cmake命令行使用
Simulation volume leetcode [general] 1706 Where does the ball meet
[istio introduction, architecture, components]
External interrupt to realize key experiment
Goldbach conjecture C language
Markdown editor Use of MD plug-in
硬件大熊原创合集(2022/06更新)
Mountaineering team (DFS)
Two schemes of unit test
What is the value of getting a PMP certificate?
Expérience de port série - simple réception et réception de données
LeetCode 715. Range 模块
Uniapp wechat applet monitoring network
Simple use of Xray