当前位置:网站首页>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 !
 Please add a picture description

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

  1. & Array name
  2. 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 .
     chart
  • 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
 chart
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
     chart
  • 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
 chart
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 .
     chart
  • 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.
     chart
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
     chart
  • 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
 chart
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
     chart
  • 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
 chart
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
     chart
  • 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
 chart
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
 chart
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
     chart
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
     chart
  • 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
     chart
    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
     chart
  • 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

 chart
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
     chart
  • 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

 Insert picture description here
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;
}

 chart

  • 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

 chart
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

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

 chart

  • 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

 chart
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

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

 chart
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

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

 chart

  • 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

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

 chart

  • 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

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

 chart

  • 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

 chart
You can see , It is consistent with the results of our analysis .

原网站

版权声明
本文为[A big cat 1201]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207070626298397.html