Programming experience (three)
C, C pointer plus 1 problem
2004-11-23
Author:
Yang Yanqing
E-mail:
BlankmanattomDotcom
Out of office:
http://blog.9cbs.net/blankman/archive/2004/11/23/programing_experience3.aspx
Recently, I have been looking for a written test and a few companies, and I have asked the relevant questions related to the pointer plus 1. I haven't considered it before. I just tested it. I found the corresponding law, tell you. (GCC environment test)
First, use Bell's pen test questions. #include
Int main (void)
{
Unsigned int a [3] = {0x01020304, 0x05060708, 0x090a0b0c}; unsigned int * p = (unsigned int *) ((int)); 1 Printf ("% x / n", * p); Return 0 ;
} [Topic Analysis] The output result of this program should be 8010203 (ie 0x08010203). The memory storage structure is shown in (Fig. 1) (in the system of Little-Endian). In the 1st statement, first transform the first address of the array A into an integer, then add 1, then force the transformation to (unsigned int *), this time P value should be 0x1235, so taken from 0x1235 to 0x1238 New integers consisting of four bytes, so it is 0x08010203. If the formula is given is (a [0] >> 8 | a [1] << 24).
Figure 1 Memory Structure Schematic
[Supplementary description] What is the output of this statement? P = a; Printf ("% D% 08X% D% D% D", (p 1) -p, * (p 1), & a [1] - & a [0], (int) (p 1) - (int) p, (char *) (p 1) - (char *) p); the result is: 1 05060708 1 4 4 The first output You may understand as a matter of course, let's look at the results . The second output value is the value of the A [1] element of the array A, that is, the address pointing to (p 1) is 0x1238, not 0x1235. why? Because when the pointer is added, it is actually a width of his point to the data type, so that the pointer can point to the next element rather than one element. The assembly code is as follows: 0040106A MOV ECX, DWORD PTR [EBP-10H] 0040106D Add ECX, 4; Note Here, actually added 4, not 1 00401070 SUB ECX, DWORD PTR [EBP-10H] 00401076 SAR ECX, 2 00401076 PUSH ECX third output should be 0x1238-0X1234 = 4, but why is 1? Because returning is the number of such elements, not the real address difference, that is, the difference is removed in the element width. The following is a stack process of the assembly code, parameter & a [1] - & a [0] of the VC. 00401043 Lea ECX, [EBP-8]; Address value 00401046 LEA EDX, [EBP-0CH]; add the address value of A [0] 00401049 SUB ECX, EDX; calculate the difference between the address value, and put Enter ECX (value 4) 0040104B SAR ECX, 2; shift two digits in ECX, which is divided by 4 (value 1) 0040104e Push ECX; parameter stack, for function printf () using fourth The output is 4 because the INT type is subtraction is the reduction in the actual number. You do not need to consider other factors. The assembly code is as follows: 00401063 MOV EDX, DWORD PTR [EBP-10H] 00401066 MOV EAX, DWORD PTR [EDX 4] 00401069 Push EAX; note! No right shift before the stack, the fifth output, talking about this, I think everyone should understand why it is 4, I only give the assembly code: 0040104F MOV Eax, DWORD PTR [EBP-10H] 00401052 Add Eax, 4 00401055 SUB EAX, DWORD PTR [EBP-10H] 00401058 Push Eax now looks back at the assembly code of the first output result.
When performing P 1, it is actually adding 4 (width of the INT type), but the result is still 1 when it is reduced, so the result is still 1. ; (p 1) -P 0040106A MOV ECX, DWORD PTR [EBP-10H] 0040106D Add ECX, 4 00401070 SUB ECX, DWORD PTR [EBP-10H] 00401073 SAR ECX, 2 00401076 PUSH ECX [posts] These previously a bit Impression, but not very certain, I trial yesterday, I found out the law. In fact, these C99 should have, my classmates are helping me find, I found it to attach the link to here. [Supplementary description]
Look at what this statement output is?
P = a;
PRINTF
"% D% 08X% D% D% D",
(p 1) -p, * (p 1), & a [1] - & a [0],
INT) (p 1) - (
Int) p,
CHAR *) (P 1) - (
Char *) P);
The result is: 1 05060708 1 4 4
The first output, you may understand it, let's take a look at the results.
The second output value is the value of the A [1] element of the array A, that is, the address pointing to (p 1) is 0x1238, not 0x1235. why? Because when the pointer is added, it is actually a width of his point to the data type, so that the pointer can point to the next element rather than one element. The assembly code is as follows:
0040106A MOV ECX, DWORD PTR [EBP-10H]
0040106D Add ECX,
4
Attention here, the actual plus is 4, not 1
00401070 SUB ECX, DWORD PTR [EBP-10H]
00401073 SAR ECX, 2
00401076 PUSH ECX
The third output should be 0x1238-0X1234 = 4, but why is 1? Because returning is the number of such elements, not the real address difference, that is, the difference is removed in the element width. The following is a stack process of the assembly code, parameter & a [1] - & a [0] of the VC.
00401043 Lea ECX, [EBP-8]
; Take the address value of A [1] 00401046 Lea EDX, [EBP-0CH]
; Add a [0] address value 00401049 SUB ECX, EDX
; Calculate the difference between the address value and put it in ECX (value 4)
0040104B SAR ECX, 2
; Turn the value in ECX to the right, which is divided by 4 (value 1)
0040104e Push ECX
Parameter stack, the function printf () uses the fourth output. Because the INT type is subtimate to the actual number, the assembly code is as follows: 00401063 MOV EDX, DWORD PTR [EBP- 10h] 00401066 MOV EAX, DWORD PTR [EDX 4] 00401069 Push Eax; Note! No right shift before the stack, the fifth output, talking about this, I think everyone should understand why it is 4, I only give the assembly code: 0040104F MOV Eax, DWORD PTR [EBP-10H] 00401052 Add Eax, 4 00401055 SUB EAX, DWORD PTR [EBP-10H] 00401058 Push Eax now looks back at the assembly code of the first output result. When performing P 1, it is actually adding 4 (width of the INT type), but the result is still 1 when it is reduced, so the result is still 1. ; (p 1) -P 0040106A MOV ECX, DWORD PTR [EBP-10H] 0040106D Add ECX, 4 00401070 SUB ECX, DWORD PTR [EBP-10H] 00401073 SAR ECX, 2 00401076 PUSH ECX [posts] These previously a bit Impression, but not very certain, I trial yesterday, I found out the law. In fact, these C99 should have, my classmates are helping me find, I found it to attach the link to here.
Figure 1 Memory Structure Schematic
[Supplementary description] What is the output of this statement? P = a; Printf ("% D% 08X% D% D% D", (p 1) -p, * (p 1), & a [1] - & a [0], (int) (p 1) - (int) p, (char *) (p 1) - (char *) p); the result is: 1 05060708 1 4 4 The first output You may understand as a matter of course, let's look at the results . The second output value is the value of the A [1] element of the array A, that is, the address pointing to (p 1) is 0x1238, not 0x1235. why? Because when the pointer is added, it is actually a width of his point to the data type, so that the pointer can point to the next element rather than one element. The assembly code is as follows: 0040106A MOV ECX, DWORD PTR [EBP-10H] 0040106D Add ECX, 4; Note Here, actually added 4, not 1 00401070 SUB ECX, DWORD PTR [EBP-10H] 00401076 SAR ECX, 2 00401076 PUSH ECX third output should be 0x1238-0X1234 = 4, but why is 1? Because returning is the number of such elements, not the real address difference, that is, the difference is removed in the element width. The following is a stack process of the assembly code, parameter & a [1] - & a [0] of the VC. 00401043 Lea ECX, [EBP-8]; Address value 00401046 LEA EDX, [EBP-0CH]; add the address value of A [0] 00401049 SUB ECX, EDX; calculate the difference between the address value, and put Enter ECX (value 4) 0040104B SAR ECX, 2; shift two digits in ECX, which is divided by 4 (value 1) 0040104e Push ECX; parameter stack, for function printf () using fourth The output is 4 because the INT type is subtraction is the reduction in the actual number. You do not need to consider other factors. The assembly code is as follows: 00401063 MOV EDX, DWORD PTR [EBP-10H] 00401066 MOV EAX, DWORD PTR [EDX 4] 00401069 Push EAX; note! No right shift before the stack, the fifth output, talking about this, I think everyone should understand why it is 4, I only give the assembly code: 0040104F MOV Eax, DWORD PTR [EBP-10H] 00401052 Add Eax, 4 00401055 SUB EAX, DWORD PTR [EBP-10H] 00401058 Push Eax now looks back at the assembly code of the first output result.
When performing P 1, it is actually adding 4 (width of the INT type), but the result is still 1 when it is reduced, so the result is still 1. ; (p 1) -P 0040106A MOV ECX, DWORD PTR [EBP-10H] 0040106D Add ECX, 4 00401070 SUB ECX, DWORD PTR [EBP-10H] 00401073 SAR ECX, 2 00401076 PUSH ECX [posts] These previously a bit Impression, but not very certain, I trial yesterday, I found out the law. In fact, these C99 should have, my classmates are helping me find, I found it to attach the link to here. [Supplementary description]
Look at what this statement output is?
P = a;
PRINTF
"% D% 08X% D% D% D",
(p 1) -p, * (p 1), & a [1] - & a [0],
INT) (p 1) - (
Int) p,
CHAR *) (P 1) - (
Char *) P);
The result is: 1 05060708 1 4 4
The first output, you may understand it, let's take a look at the results.
The second output value is the value of the A [1] element of the array A, that is, the address pointing to (p 1) is 0x1238, not 0x1235. why? Because when the pointer is added, it is actually a width of his point to the data type, so that the pointer can point to the next element rather than one element. The assembly code is as follows:
0040106A MOV ECX, DWORD PTR [EBP-10H]
0040106D Add ECX,
4
Attention here, the actual plus is 4, not 1
00401070 SUB ECX, DWORD PTR [EBP-10H]
00401073 SAR ECX, 2
00401076 PUSH ECX
The third output should be 0x1238-0X1234 = 4, but why is 1? Because returning is the number of such elements, not the real address difference, that is, the difference is removed in the element width. The following is a stack process of the assembly code, parameter & a [1] - & a [0] of the VC.
00401043 Lea ECX, [EBP-8]
; Take the address value of A [1] 00401046 Lea EDX, [EBP-0CH]
; Add a [0] address value 00401049 SUB ECX, EDX
; Calculate the difference between the address value and put it in ECX (value 4)
0040104B SAR ECX, 2
; Turn the value in ECX to the right, which is divided by 4 (value 1)
0040104e Push ECX
Parameter stack, the function printf () uses the fourth output. Because the INT type is subtimate to the actual number, the assembly code is as follows: 00401063 MOV EDX, DWORD PTR [EBP- 10h] 00401066 MOV EAX, DWORD PTR [EDX 4] 00401069 Push Eax; Note! No right shift before the stack, the fifth output, talking about this, I think everyone should understand why it is 4, I only give the assembly code: 0040104F MOV Eax, DWORD PTR [EBP-10H] 00401052 Add Eax, 4 00401055 SUB EAX, DWORD PTR [EBP-10H] 00401058 Push Eax now looks back at the assembly code of the first output result. When performing P 1, it is actually adding 4 (width of the INT type), but the result is still 1 when it is reduced, so the result is still 1. ; (p 1) -P 0040106A MOV ECX, DWORD PTR [EBP-10H] 0040106D Add ECX, 4 00401070 SUB ECX, DWORD PTR [EBP-10H] 00401073 SAR ECX, 2 00401076 PUSH ECX [posts] These previously a bit Impression, but not very certain, I trial yesterday, I found out the law. In fact, these C99 should have, my classmates are helping me find, I found it to attach the link to here.
Figure 1 Memory Structure Schematic
[Supplementary description] What is the output of this statement? P = a; Printf ("% D% 08X% D% D% D", (p 1) -p, * (p 1), & a [1] - & a [0], (int) (p 1) - (int) p, (char *) (p 1) - (char *) p); the result is: 1 05060708 1 4 4 The first output You may understand as a matter of course, let's look at the results . The second output value is the value of the A [1] element of the array A, that is, the address pointing to (p 1) is 0x1238, not 0x1235. why? Because when the pointer is added, it is actually a width of his point to the data type, so that the pointer can point to the next element rather than one element. The assembly code is as follows: 0040106A MOV ECX, DWORD PTR [EBP-10H] 0040106D Add ECX, 4; Note Here, actually added 4, not 1 00401070 SUB ECX, DWORD PTR [EBP-10H] 00401076 SAR ECX, 2 00401076 PUSH ECX third output should be 0x1238-0X1234 = 4, but why is 1? Because returning is the number of such elements, not the real address difference, that is, the difference is removed in the element width. The following is a stack process of the assembly code, parameter & a [1] - & a [0] of the VC. 00401043 Lea ECX, [EBP-8]; Address value 00401046 LEA EDX, [EBP-0CH]; add the address value of A [0] 00401049 SUB ECX, EDX; calculate the difference between the address value, and put Enter ECX (value 4) 0040104B SAR ECX, 2; shift two digits in ECX, which is divided by 4 (value 1) 0040104e Push ECX; parameter stack, for function printf () using fourth The output is 4 because the INT type is subtraction is the reduction in the actual number. You do not need to consider other factors. The assembly code is as follows: 00401063 MOV EDX, DWORD PTR [EBP-10H] 00401066 MOV EAX, DWORD PTR [EDX 4] 00401069 Push EAX; note! No right shift before the stack, the fifth output, talking about this, I think everyone should understand why it is 4, I only give the assembly code: 0040104F MOV Eax, DWORD PTR [EBP-10H] 00401052 Add Eax, 4 00401055 SUB EAX, DWORD PTR [EBP-10H] 00401058 Push Eax now looks back at the assembly code of the first output result.
When performing P 1, it is actually adding 4 (width of the INT type), but the result is still 1 when it is reduced, so the result is still 1. ; (p 1) -P 0040106A MOV ECX, DWORD PTR [EBP-10H] 0040106D Add ECX, 4 00401070 SUB ECX, DWORD PTR [EBP-10H] 00401073 SAR ECX, 2 00401076 PUSH ECX [posts] These previously a bit Impression, but not very certain, I trial yesterday, I found out the law. In fact, these C99 should have, my classmates are helping me find, I found it to attach the link to here. When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements (the result is two array elements. The difference between the subscript) Previous: Programming Experience (2) - "Function Call When the parameter stack order (2004-10-24)" Next: Programming experience (four) - "Use class Member function acts as a thread execution function "declaration: original, copyright, please indicate the source if you need to reprint. http://blog.9cbs.net/blankman/archive/2004/11/23/programing_experience3.aspx