Everything starts from here.
A freshman sent me a C ++ question via QQ:
int c = 8, b = 3;c += c-- | ++b;
Ask the value of C. After computation, we can see that C is 19, and a C # console project is created at will. It is a tragedy... C # outputs 20. Re-calculate again or 19 ah, and quickly re-build a C ++ console project ran out of the result of 19. Why is C ++ different from C?
Verification 1
I learned from the online query about the C # order of value. What is the specific situation? Let's disassemble:
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 33 (0x21) .maxstack 4 .locals init ([0] int32 c, [1] int32 b) IL_0000: nop IL_0001: ldc.i4.8 IL_0002: stloc.0 IL_0003: ldc.i4.3 IL_0004: stloc.1 IL_0005: ldloc.0 IL_0006: ldloc.0 IL_0007: dup IL_0008: ldc.i4.1 IL_0009: sub IL_000a: stloc.0 IL_000b: ldloc.1 IL_000c: ldc.i4.1 IL_000d: add IL_000e: dup IL_000f: stloc.1 IL_0010: or IL_0011: add IL_0012: stloc.0 IL_0013: ldloc.0 IL_0014: call void [mscorlib]System.Console::WriteLine(int32) IL_0019: nop IL_001a: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() IL_001f: pop IL_0020: ret } // end of method Program::Main
Through the Il code, we can clearly see its computing process:
- 0 ~ The four rows assign values to the variables. In the call stack, 0 indicates that the C value of the variable is 8, and 1 indicates that the B value of the variable is 3.
- The value of C is cached in five rows and stored in the evaluation stack. The cached value is 8.
- A c value is cached in six rows, and the cached value is 8.
- 7 ~ Row A executes c = C-1, and the value of C is 7.
- B ~ Row F executes B = B + 1 and leaves a copy. The value is 4.
- 8 and B ~ The value of 4 or left in Row F is 12.
- Result 12 in row 11 and row 10 plus 8 cached in Row 5 is 20
- 12 rows are stored in variable C
C + = c -- | ++ B; equivalent to C = C + (c -- | ++ B). Through disassembly, we can see that:
- The order in which C # is evaluated from left to right is not changed because of the operation order. The value of the first C on the right of the equal sign is cached from the beginning.
- C -- after evaluationSettled immediatelyThe value of the C variable changes to 7 at this time, but the value of the C variable does not affect the final result of the formula. The reason is as follows: 1.
- Convert the formulaC = C + (-- c | ++ B );The obtained value is 15 (8 + (7 | 4). After disassembly, we observe that the conclusions are the same as the first one. c -- and -- C only affect the calculation results in parentheses.
According to the above conclusion, we changed the formulaC = (c -- | ++ B) + C;And the result is 19.
Proof 2
So how is C ++ executed? Continue, decompilation:
(The disassembly program is based on the C ++ debug compilation result of vs2013. The disassembly code of GCC 4.6.1 is slightly different, and the execution process is consistent. The conclusion is only limited to the two compiling environments) c ++ execution process:
- Use the eax register for B = B + 1
- Use the ECX register for C = 8 + (8 | 4) (B = 4)
- Use the edX register for C = C-1
We can see from the disassembly:
- C ++ does not cache values, and C ++ does not specify the order of values.
- C ++ takes the value only during calculation, so the result of c = (c -- | ++ B) + C; is 19.
- C ++ is C at the end of the entire formula -- that is to say, the result is 19, not 20, not because the or in the brackets causes C to be 7 in the final addition,It is because c -- settlement is performed only after the formula value assignment is complete.. (Teachers, are you right ?)
Finally, verify that the formula changedC = C * 2 + (c -- | ++ B );The output result of C ++ is 27,8*2 + 12 = 28-1 = 27. The disassembly can also see the sub executed at the end.
Last
- If you are learning C ++, do not use C # To verify the answers to your assignment questions...
- Let '+ +' only appear in the for statement...