[C Language] Detailed Explanation of Pointer and Array Pen Test Questions

Table of contents

1. Array

1. One-dimensional array

2. Character array

3. Two-dimensional array 

Two, the pointer 

 Written test question 1

 Written test question 2

 Written test question 3

 Written test question 4

 Written test question 5

 Written test question 6

Written test question 7

Written test question 8 (difficult) [There will be qualitative gains if you understand it]


 

Here we need to understand the meaning of the array name

  • sizeof(array name), where the array name represents the entire array, and the calculation is the size of the entire array
  • &Array name, the array name here also represents the entire array, and the size of the entire array is taken out
  • In addition to the above, the array name indicates the address of the first element of the array

1. Array

1. One-dimensional array

Analyze the code below and judge the output result

//一维数组
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));

(1) sizeof(a)
sizeof(a) is sizeof(array name), so the size of the entire array is sought. The array element type is int (accounting for 4 bytes), and there are 4 elements.
【Result】16

(2)  sizeof( a+0 )
sizeof(a+0) It should be seen clearly here that this is the general situation except the above two cases, where a represents the address of the first element of the array, and a+0 is still the first element of the array The element address can be understood as &a[0], note that the address is taken out here. The address is generally 4/8 bytes (32-bit platform/64-bit platform)

[Result] 4 (in the x86 environment)/8 (in the x64 environment)
(3) sizeof(*a) 
sizeof(*a), where a is also the address of the first element of the array, and *a is dereferenced to get the first element 1 (int type)
[Result] 4
(4) sizeof(a+1)
sizeof(a+1) indicates the address size of the second element (4/8)
[Result] 4/8
(5) sizeof(a [1])
sizeof(a[1]) calculates the size of the second element
[result] 4
(6) sizeof(&a)
sizeof(&a), the address a here represents the entire array, but Or the address, the size of the address (4/8)
【Result】4/8
(7) sizeof(*&a) 
sizeof(*&a), here are two ways to understand 1. &a the entire array, *&a dereference to get the array It is equivalent to sizefo(a), *&, which cancel each other out, and calculate the entire array. 2. Because the type of &a is int( * ) [4], array pointer (pointer to array), array type, the array here has 4 int elements, and the calculation is also the entire array [Result
] 16

(8) sizeof(&a+1) 

sizeof(&a+1) means spanning an entire array, but it is also an address

【Result】 4/8  

(9) sizeof(&a[0])

sizeof(&a[0]), where &a[0] indicates the address of the first element

【Result】 4/8

(10) sizeof(&a[0]+1)

sizeof(&a[0]+1) indicates that the address of the second element is taken out

【Result】 4/8

diagram

2. Character array

Analyze the code below and judge the output result

//字符数组
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));

//strlen求大小
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));

(1) sizeof(arr)

sizeof(arr), calculates the size of the entire array, the array has 6 char type characters

【Result】  6

(2) sizeof(arr+0)

sizeof(arr+0), here is the address of the first element of the array + 0, or the address of the first element of the array

【Result】4/8

(3) sizeof(*arr)

sizeof(*arr), where *arr is equivalent to arr[0], which calculates the size of the first element of the array

【Result】1

(4) sizeof(arr[1])

sizeof(arr[1]), calculates the size of the second element of the array (the array subscript starts from 0)

【Result】1

(5) sizeof(&arr)

sizeof(&arr), &arr, takes the address of the entire array

【Result】4/8

(6) sizeof(&arr+1)

&arr+1, which means skipping the address of the entire array

【Result】4/8

(7) sizeof(&arr[0]+1)

&arr[0]+1 represents the address of the second element

【Result】4/8

 strlen counts the number of characters before the character '\0'

 (8) strlen(arr)

 strlen(arr), calculates the length of the entire character array, but there is no '\0' in the character array, the system keeps looking down until it finds '\0', and the program stops executing

[Result]  random value

 (9) strlen(arr+0)

 strlen(arr+0), here is to find '\0' from the first element of the array, there is no '\0' in the known array

[Result]  random value

 (10) strlen(*arr)

strlen(*arr), *arr will get the first element a strlen('a'), the address of character a is 97, so it will start to access and search from address 97 (accessing the space corresponding to address 97 is an illegal access space), the system will report an error

[Result]   error

 (11) strlen(arr[1])

The arr[1] here represents the character b, and the strlen function will access from the address 98 corresponding to 'b' (illegal access)

[Result]   error

 (12) strlen(&arr)

&arr, indicating the address of the entire array, will start accessing from the address of the first element of the array to find '\0'

[Result]  random value

 (13) strlen(&arr+1)

This is to skip the entire array to find '\0'

[Result]  random value

 (14) strlen(&arr[0]+1)

&arr[0] + 1 is the address of the second element. The result is also a random value

[Result]  random value

Here it becomes a string "abcdef" element has abcdef \0 

Analyze the code below 

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

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

 (1) sizeof(arr)

The size of the entire array calculated here "abcdef" element has abcdef \0 

 【Result】 7

(2) sizeof(arr+0)

arr+0 first element address

 【Result】  4/8

(3) sizeof(*arr)

Calculate the size of the first element

 【Result】  1

(4) sizeof(arr[1])

This calculates the size of the second element

 【Result】  1

(5) sizeof(&arr)

Calculate the size of the address of the entire array

 【Result】  4/8

(6) sizeof(&arr+1)

The calculation is to skip the size of the address of the integer group

 【Result】  4/8

(7) sizeof(&arr[0]+1)

Find the size of the second element address

 【Result】  4/8

 (8) strlen(arr)

What is asked here is the length of the string, that is, the number of characters before '\0'

 【Result】  6

(9) strlen(arr+0)

arr+0 Find '\0' backward from the first character

 【Result】  6

(10) strlen(*arr)

*arr is the character 'a', the ASCII code corresponding to the character a is 97, access from address 97 (illegal access)

 [Result]  error

(11) strlen(arr[1])

arr[1] is character 'b', the ASCII code corresponding to character b is 98, access from address 98 (illegal access)

 [Result]  error

(12) strlen(&arr)

The size of the address of the entire array calculated here, but the value of the address is the same as the value of the address of the first element of the array

 【Result】  6

(13) strlen(&arr+1)

Find '\0' starting from the address of the skipped integer array

 [Result]  random value

(14) strlen(&arr[0]+1)

Calculate the length of the string starting from the second element

 【Result】  5

It becomes a character pointer char *p = "abcdef"; (we know that the address of the first character is stored in the character pointer) 

 Analyze the code below

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

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

(1) sizeof(p)

p stores the address of the first character

【Result】4/8

(2) sizeof(p+1)

p stores the address of b

【Result】4/8

(3) sizeof(*p)

*p is equivalent to *(p+0), p[0] is the size of a

【Result】1

(4) sizeof(p[0])

p[0] is the size of a

【Result】1

(5) sizeof(&p)

Get the address type of the pointer variable p is char **

【Result】4/8

(6) sizeof(&p+1)

Get the address of the pointer variable p and then the address of +1

【Result】4/8

(7) sizeof(p[0]+1)

address of b

【Result】4/8

(8) strlen(p)

Finding '\0' from the address of the first character is equivalent to calculating the length of the string

【Result】 6

(9) strlen(p+1)

Calculate the string length from the second character

【Result】5

(10) strlen(*p)

*p is the character 'a', the ASCII code corresponding to the character a is 97, access from address 97 (illegal access)

[Result] error

(11) strlen(p[0])

p[0] is the character 'a', the ASCII code corresponding to the character a is 97, access from address 97 (illegal access)

[Result] error

(12) strlen(&p)

The address of the pointer variable p starts to find '\0'

【Result】 random value

(13) strlen(&p+1)

The address of the pointer variable p + 1 starts to find '\0'

[Result] random value

(14) strlen(&p[0]+1)

Calculate the length of the string starting from the second element

【Result】5

3. Two-dimensional array 

Analyze the code below

//二维数组
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]));

(1) sizeof(a)

sizeof(a) finds the size of the entire array 

【Result】48

(2) sizeof(a[0][0])

Calculates the size of the first element

【Result】4

(3) sizeof(a[0])

a[0] represents all the elements in the first row, and the calculation is the size of the elements in the first row

【Result】16

(4) sizeof(a[0]+1)

a[0]+1 represents the address of the second element in the first row

【Result】4/8

(5) sizeof(*(a[0]+1))

Calculates the size of the second element in the first row

【Result】4

(6) sizeof(a+1)

a+1 is equivalent to the second line of the array represented by a[1], sizeof(a+1) is the address size of the second line of the array

【Result】4/8

(7) sizeof(*(a+1))

sizeof(*(a+1)) is equivalent to sizeof(a[1]) to find the size of the second row array

【Result】16

(8) sizeof(&a[0]+1)

&a[0]+1 means the address of the second line

【Result】4/8

(9) sizeof(*(&a[0]+1))

The dereference gets the array of the second row

【Result】16

(10) sizeof(*a)

*a is the array of the first line *a <-->*(a+0)<-->a[0]

【Result】16

(11) sizeof(a[3])

Pay attention to the subscript of the array here, the array is 3 lines (the subscript should be 0~2), indicating that the array is out of bounds, but it is still calculated according to the size of the array of one line

[Result]   16 (but the array is out of bounds)

Two, the pointer 

Tips before doing the questions: draw a picture

 Written test question 1

#include<stdio.h>
int main() 
{
	int a[5] = {1,2,3,4,5};
	int* ptr = (int*)(&a + 1);
	printf("%d,%d",*(a+1),*(ptr-1));
	return 0;
}
//程序的结果是什么?

[Result] 2, 5

【Analysis】

Written test question 2

#include<stdio.h>
struct Test 
{
	int Num;
	char pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;
//假设*p 的值为0x100000 如下表表达式的值分别是多少?
//已知,结构体Test类型变量大小是20字节
int main() 
{
	printf("%p\n",p+0x1);
	printf("%p\n",(unsigned long)p+0x1);
	printf("%p\n",(unsigned int*)p+0x1);
	return 0;
}

【result】

00100014
00100001
00100004

【Analysis】

p is a structure pointer variable, where 0x1 means 1, p+0x1 means skip a structure (20 bytes) 0x100000+0x000014 == 0x100014 output the first one is 0x100014

(unsigned long) p Here is a mandatory type conversion, converted to a numeric unsigned long type (note that it is a numeric value, not an address) value 0x100000+0x1 == 0x 100001

(unsigned int*)p is converted to an unsigned integer pointer, (unsigned int*)p+0x1 skips four bytes 0x100004

Written test question 3

//系统使用小端模式
#include<stdio.h>
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;
}

【result】

4,2000000

【Analysis】

Here ptr1[-1] is equivalent to ptr1 -1, (int*)((int)a + 1); here (int)a is converted into a value and then +1 and then converted into an address (note that the little endian mode 0x is adopted 02 00 00 00)

 Written test question 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;
}

【Result】1

[Analysis] p[0] prints the first element of the first line, note that the parentheses (0, 1) == 1

 Written test question 5

#include<stdio.h>
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;
}

【Result】FFFFFFFC-4

[Analysis] p = a, where p is the array pointer int(*)[4] (4 columns), &p[4][2] - &a[4][2] This is the small address-big address. There is no signed or unsigned distinction when printing %p (hexadecimal)

&p[4][2] - &a[4][2]   //-4
10000000000000000000000000000100
11111111111111111111111111111011
1111 1111 1111 1111 1111 1111 1111 1100
   F      F      F      F      F      F      F      C

  Written test question 6

#include<stdio.h>
int main() 
{
	int aa[2][5] = {1,2,3,4,5,6,7,8,9,10};
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa+1));
	printf("%d,%d",*(ptr1-1),*(ptr2-1));
	return 0;
}

【Result】10,5

【Analysis】

   Written test question 7

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

【Result】 at

[Analysis] pa stores the address of the first element (the address of the first string), pa+1, then pa points to the address of the second string, *pa gets the address of the second string

Written test question 8 (difficult) [There will be qualitative gains if you understand it]

#include<stdio.h>
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;
}

【result】

POINT
IS
ST
EW

【Super detailed analysis】

This question uses three-level pointers.

Look at the diagram first (storage before printing)

char *c[ ] is an array of pointers (the element types are all pointers), so the address of the first character of each string is stored in the c array

The cp array stores the address of each element of the c array, and the cpp third-level pointer points to the first element of the cp array

(1) printf("%s\n",**++cpp);

**++cpp, here, since the prefix self-increment (++) is higher than the priority of indirect access (*), it is to cpp+1 first, and then dereference

cpp+1 points to cp[1], *(cpp+1) gets c+2, then dereferences *(c+2), prints out the string POINT

(2) printf("%s\n",*--*++cpp+3);

*--*++cpp+3, first use a space to distinguish * -- * ++cpp +3, here it should be noted that the cpp at this time has already pointed to cp[1] instead of cp[0]

Continue to calculate * -- * ++cpp +3, where ++cpp points to cp[2], and then dereferences it (*++cpp) to get c+1

c+1, then * -- * ++cpp +3 becomes *--(c+1)+3, this --(c+1) becomes c, and then dereferences c to get

c[0], c[0] stores the address of the first character of "ENTER", which can be understood as c+0, and then +3 to it, that is, c+3,

 print string get ER

(3) printf("%s\n",*cpp[-2]+3);

cpp, according to the above self-increment, cpp points to cp[2]

 *cpp[-2], the subscript reference operator here has a higher priority than *, first cpp[-2], cpp[-2] is equivalent to *(cpp-2), *(cpp-2) obtained It is c+3, because *cpp[-2]+3 has a dereference before, so *(c+3) gets the address of the first character of the string "FIRST", and then +3 points to S

  print string get  ST

(4) printf("%s\n",cpp[-1][-1]+1);

cpp[-1][-1]+1, first determine that cpp points to cp[2], then cpp[-1][-1] +1 is equivalent to * ( * (cpp-1) - 1) +1 

cpp-1 points to cp[1], dereferencing gets c+2, c+2 - 1 gets c+1, dereferencing gets the address of the first character of the character "NEW", and then +1 the pointer points to

 Print the string to get  EW

Guess you like

Origin blog.csdn.net/qq_72505850/article/details/132396435