With the above: ++ (--) there are too many confusing places, (I ++) + (I ++) and (++ I) + (++ I) what is the difference? Why is it different? If you understand it from the machine's point of view, it will suddenly become more open.
Let's first look at the program section:
Int main ()
{
Int I = 3;
Int j = (I ++) + (I ++ );
// Int j = (++ I) + (++ I );
Printf ("% d, % d \ n", I, j );
}
(1) In VC 6.0:
For (I ++) + (I ++ ):
Result: I = 5, j = 6.
The compilation code is (with detailed comments ):
8B 45 FC mov eax, dword ptr [ebp-4]; I-> eax
03 45 FC add eax, dword ptr [ebp-4]; I + I = 6
89 45 F8 mov dword ptr [ebp-8], eax; 6-> j
8B 4D FC mov ecx, dword ptr [ebp-4]; I-> ecx (= 3)
83 C1 01 add ecx, 1; ecx = 4
89 4D FC mov dword ptr [ebp-4], ecx; 4-> I
8B 55 FC mov edx, dword ptr [ebp-4]; I-> edx
83 C2 01 add edx, 1; edx = 5
89 55 FC mov dword ptr [ebp-4], edx; 5-> I
For (++ I) + (++ I ):
Result: I = 5, j = 10.
The compilation code is as follows:
8B 45 FC mov eax, dword ptr [ebp-4]; I-> eax (= 3)
83 C0 01 add eax, 1; eax = 4
89 45 FC mov dword ptr [ebp-4], eax; 4-> I
8B 4D FC mov ecx, dword ptr [ebp-4]; I-> ecx
83 C1 01 add ecx, 1; ecx = 5
89 4D FC mov dword ptr [ebp-4], ecx; 5-> I
8B 55 FC mov edx, dword ptr [ebp-4]; I-> edx
03 55 FC add edx, dword ptr [ebp-4]; edx = 10, that is, I + I
89 55 F8 mov dword ptr [ebp-8], edx; 10-> j
(2) Under gcc 3.2.2:
For (I ++) + (I ++ ):
Result: The Assembly Code of I = 5, j = 6 is:
C7 45 fc 03 00 00 00 movl $3,-4 (% ebp); 3-> I
8b 55 fc movl-4 (% ebp), % edx; I-> edx (= 3)
8b 45 fc movl-4 (% ebp), % eax; I-> eax (= 3)
8d 04 10 leal (% eax, % edx), % eax; I + I = 6-> eax
89 45 f8 movl % eax,-8 (% ebp); 6-> j
8d 45 fc leal-4 (% ebp), % eax; & I-> eax
Ff 00 incl (% eax); I ++, that is, I = 4. Note that this is the indirect addressing of registers.
8d 45 fc leal-4 (% ebp), % eax; & I-> eax
Ff 00 incl (% eax); I ++, that is, I = 5
For (++ I) + (++ I ):
Result: I = 5, j = 10.
The compilation code is as follows:
Movl $3,-4 (% ebp); 3-> I
Leal-4 (% ebp), % eax; & I-> eax
Incl (% eax); I ++, that is, I = 4
Leal-4 (% ebp), % eax; & I-> eax
Incl (% eax); I ++, I = 5
Movl-4 (% ebp), % eax; I-> eax, eax = 5
Addl-4 (% ebp), % eax; I + I-> eax, eax = 10
Movl % eax,-8 (% ebp); 10-> j
It can be seen that for VC6.0 and gcc, the results are the same, but the assembly code generated by gcc 3.2.2 is much more efficient and concise than VC6.0. This may be because of the early appearance of VC 6.0.
(3) What will happen if this code is implemented in java?
Program:
Public class TestAdd {
Public static void main (String [] args ){
Int I = 3;
Int j = (I ++) + (I ++); // 5, 7
// Int j = (++ I) + (++ I); // 5, 9
System. out. println (I + "," + j );
}
}
For (++ I) + (++ I ):
I = 5, j = 9. Unexpected result!
Let's take a look at its bytecode:
// J = (++ I) + (++ I)
// 5, 9
0: iconst_3; constant 3 into the stack
1: istore_1; 3 popped up from the stack and saved to I, I = 3
2: iinc 1, 1; I ++, I = 4
5: iload_1; press I into the stack, that is, 4 into the stack
6: iinc 1, 1; I ++, I = 5
9: iload_1; I inbound stack, that is, 5 inbound Stack
10: iadd; the number of two int types is added from the stack.
11: istore_2; pop up 9 from the stack and save it to j, that is, j = 9
For (I ++) + (I ++ ):
I = 5, j = 7. The results are also unexpected!
Let's also look at its bytecode:
// J = (I ++) + (I ++)
// 5, 7
0: iconst_3; constant 3 into the stack
1: istore_1; 3 popped up from the stack and saved to I, I = 3
2: iload_1; I inbound stack, that is, 3 inbound Stack
3: iinc 1, 1; I ++, that is, I = 4
6: iload_1; I inbound stack, that is, 4 inbound Stack
7: iinc 1, 1; I ++, that is, I = 5; Note: 5 is not included in the stack, so the number of stacks is 3 and 4 at this time.
10: iadd; the number of two int types is added from the stack.
11: istore_2; pop up 7 from the stack and store it to j, that is, j = 7
Why is there such a difference between Java and VC/gcc? In fact, the reason is very simple. VC/gcc generates local code, while X86 processor is based on the register architecture, that is, if it needs to add two numbers, it first moves the two numbers to the register and then performs addition operations. The Java virtual machine is a stack-based architecture. If you want to add two numbers, it will first pop up two numbers, then perform addition operations, and then import the results to the stack.