Summary
1) ++ and - participate in the mixed operation result is uncertain, such as r = (i++) + (i++); etc.
- C++ only specifies the relative execution order
corresponding to ++ and - (the
value and auto-increment)
- ++ and - The assembly instructions corresponding to
- In the mixed operation, the
assembly instruction of ++ and - may be interrupted (the value and auto-increment may be interrupted, and other codes are inserted in the middle)
2) The greedy method of the
- The compiler
as many characters as possible
from left to right, one by one 16176b873dc766
- When the read character
cannot form a legal symbol with the already read character
3) The space can be used as the rest of a complete symbol of
compiler reads the space, it will immediately process the previously read symbol.
Analysis of ++ and - Operator
1、Demo1
What is the output of the following code?
int i = 0; int r = 0; r = (i++) + (i++) + (i++); printf("i = %d\n, r = %d\n", i, r); r = (++i) + (++i) + (++i); printf("i = %d\n, r = %d\n", i, r);
Preliminary analysis of the code:
第一行输出:i = 3, r = 3; // 按照从左向右的计算方法,i先取值,再自增, // 则r = 0 + 1 + 2 = 3; 第二行输出:i = 6, r = 16; // 同上,r = 4 + 5 + 6 = 15;
The actual output of the above code in the VS2015 compiler is:
i = 3, r = 0;
i = 6, r = 18;
View the disassembly result with the help of the Vs compiler:
Code analysis:
对于r = (i++) + (i++) + (i++); // 先取了i的值做了相加,赋值给r;然后i自增3次
在汇编层面,做的操作依次是:
1)00C542BC mov 将i代表的这个地址中的值放到寄存器eax中,为0
2)00C542BF add eax的值和i的值累加,累加和仍然为0
3)00C542C5 mov 将eax里的值放到r变量代表的内存里,
所以r的值为0
4)后面做了3次相同的操作:将i变量内存里的值放到ecx寄存器里,然后加1,
再把ecx里的值放回i变量的内存里;重复2次
所以i的值为3
对于r = (i++) + (i++) + (i++); // 先给i自增了3次;然后把i的值加3次给了r
在汇编层面,做的操作依次是:
1)009A42F8 到 009A42FE 将i代表的这个地址中的值放到寄存器eax中;
然后eax里的值自增1;
写回i的内存里,此时i的值为4
重复2次后,i的值为6
所以i的值为6
2)009A4313 mov 把i里的值移动到eax寄存器中,eax里的值为6
3)009A4316 add eax里的值加上i的值,即6+6,eax里的值为12
4)009A4319 add eax里的值加上i的值,即12+6,eax里的值为18
5)009A4319 mov eax里的值写回r代表的内存里
所以r的值为18
This piece of code, our analysis and the actual compiler results are very different; then what about other compilers?
bcc compiler and the vc compiler are the same, while
gcc compiler are "r = 0 and r = 16"
The output result of the above code in the java compiler:
// test.java
public static void main(String[] args) {
System.out.println("test.java file name must be equal to the class name test");
int i = 0;
int r = 0;
r = (i++) + (i++) + (i++);
System.out.println("i = " + i + ", r = " + r);
r = (++i) + (++i) + (++i);
System.out.println("i = " + i + ", r = " + r);
}
// 编译:javac test.java
// 执行:java test
// 输出:i = 3, r = 3
i = 6, r = 15 和分析的一致
The above test description: ++ and - participate in the mixed operation result is uncertain
- C++ only specifies the relative execution order of ++ and-corresponding instructions
- ++ and-the corresponding assembly instructions are not necessarily executed continuously
- In mixed operations, the assembly instructions of ++ and - may be interrupted in execution
2、Demo2
What is the output of the following code?
int i = 0; int j = ++i+++i+++i; int a = 1; int b = 4; int c = a+++b; int* p = &a; b = b/*p; printf("i = %d\n", i); printf("j = %d\n", j); printf("a = %d\n", a); printf("b = %d\n", b); printf("c = %d\n", c);
compiler's greedy method
- The compiler
as many characters as possible one by one
from left to right
- When the read character
cannot form a legal symbol with the character that has been read
Code analysis:
int j = ++i+++i+++i;
// 编译器先读到1个'+',不知道啥意思;
// 继续读到1个'+',它觉得这是个前置的'++'
// 然后读到了i,确定了这是个'++i'表达式
// 继续读到1个'+',这可能是一个加法的运算符 '+'
// 继续读到1个'+',这时候判断是一个后置的 '++',后面再读任何数都不对了,读到变量,不合法;读到符号,也不对;
// 这时候编译器就停止处理了,所以编译器就得到了 “++i++”
// 然后计算得到了 “1++”,对一个右值1进行自增,自然会编译错误!
int c = a+++b;
// 编译器依次读了3个字符'a++',知道这是个后置的++
// 然后读到了1个'+',觉得这个可能是个加法运算符
// 继续读到了b,后面也没有其他字符了,所以得到了 (a++) + b
// 计算得到了c = 5
b = b/*p; // error,编译器会将/*识别为注释,因此整个程序会编译失败
// 如果愿意是用b的值除以*p的值,那么就应该用括号或者空格表明
b = b / (*p); 或 b = b / *p;
This article is summarized from "C Language Advanced Course" by Tang Zuolin from "Ditai Software Academy".
If there are any errors or omissions, please correct me .
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。