关于i++特别题型收集
第一题:
#include <iostream> int main(int argc,char **argv) { int a,x; for (a=0,x=0; a<=1 && !x++ ; a++) { a++; } std::cout<<a<<" "<<x<<std::endl; return 0 ; }
结果为:2,1
反汇编主要代码如下:
for (a=0,x=0; a<=1 && !x++ ; a++) 00401588 mov dword ptr [ebp-4],0 ; a = 0 0040158F mov dword ptr [ebp-8],0 ; x = 0 00401596 jmp main+31h (004015a1) ;这里第一次循环跳过了下面三句指令
00401598 mov eax,dword ptr [ebp-4] ;这三句指令是特别的针对for判断语句中的第三个语句 a++的,只会再第二次循环开始才执行 0040159B add eax,1 0040159E mov dword ptr [ebp-4],eax
004015A1 cmp dword ptr [ebp-4],1 ; 判断a<=1 004015A5 jg main+52h (004015c2)
004015A7 mov ecx,dword ptr [ebp-8] ;这六句是先判断!x 004015AA mov edx,dword ptr [ebp-8] 004015AD add edx,1 ;然后x = x+1 ,但是这句跟判断!x没有关系 004015B0 mov dword ptr [ebp-8],edx 004015B3 test ecx,ecx 004015B5 jne main+52h (004015c2)
7: { 8: a++; 004015B7 mov eax,dword ptr [ebp-4] 004015BA add eax,1 004015BD mov dword ptr [ebp-4],eax 9: } 004015C0 jmp main+28h (00401598)
根据反汇编可以得出:for 后面的判断语句中,第一部分只在第一次循环前执行;第二部分则是在每次循环都执行;第三部分,只在第二次循环才开始执行.
变形题:
#include <iostream> int main(int argc,char **argv) { int a,x; for (a=0,x=0; a<=1 && !x++ ;) // 这里少了第三个a++ { a++; } std::cout<<a<<" "<<x<<std::endl; return 0 ; }
结果为:1,2
反汇编:
for (a=0,x=0; a<=1 && !x++ ;) 00401588 mov dword ptr [ebp-4],0 ; a = 0 0040158F mov dword ptr [ebp-8],0 ; x = 0
00401596 cmp dword ptr [ebp-4],1 ; 判断 a<=1 0040159A jg main+47h (004015b7)
0040159C mov eax,dword ptr [ebp-8] ;前面的判断成立后,再进行!x判断 0040159F mov ecx,dword ptr [ebp-8] 004015A2 add ecx,1 ; x = x+1 与判断独立开来的,并且先进性 ++ 004015A5 mov dword ptr [ebp-8],ecx
004015A8 test eax,eax ; 判断!x 004015AA jne main+47h (004015b7)
7: { 8: a++; 004015AC mov edx,dword ptr [ebp-4] 004015AF add edx,1 004015B2 mov dword ptr [ebp-4],edx 9: } 004015B5 jmp main+26h (00401596)
第2题:
#include <stdio.h> int main(int argc,char **argv) { int b= 3; int arr[] = {6,7,8,9,10}; int *ptr= arr; *(ptr++) += 123; ;这里很容易明白,是将下标为0的元素 6 +123 = 129 ,然后在讲ptr++,指向下一元素,即元素7 printf("%d,%d\n",*ptr,*(++ptr)); ;这句看下面的反汇编 return 0 ; }
答案为:8,8
反汇编:
printf("%d,%d\n",*ptr,*(++ptr)); 0040106E mov edx,dword ptr [ebp-1Ch] ; 现将 ptr = ptr +sizeof(int) 00401071 add edx,4 00401074 mov dword ptr [ebp-1Ch],edx
00401077 mov eax,dword ptr [ebp-1Ch] ; printf遵循_cdecl方式,即从右往左依次将参数压入栈中,所以执行最右边的参数 0040107A mov ecx,dword ptr [eax] 0040107C push ecx
0040107D mov edx,dword ptr [ebp-1Ch] 00401080 mov eax,dword ptr [edx] 00401082 push eax 00401083 push offset string "%d,%d\n" (0042201c) 00401088 call printf (004010d0) 0040108D add esp,0Ch
变形2_1:讲
printf("%d,%d\n",*ptr,*(++ptr)) 改为:
printf("%d,%d\n",*(++ptr),*ptr)
结果变为:8,7
反汇编代码:
1 printf("%d,%d\n",*(++ptr),*ptr); 2 0040106E mov edx,dword ptr [ebp-1Ch] ;讲最右边的参数*ptr压入栈中 3 00401071 mov eax,dword ptr [edx] 4 00401073 push eax
5 00401074 mov ecx,dword ptr [ebp-1Ch] ;执行ptr = ptr +sizeof(int) 6 00401077 add ecx,4 7 0040107A mov dword ptr [ebp-1Ch],ecx
8 0040107D mov edx,dword ptr [ebp-1Ch] 将倒数第二个参数压入栈中 9 00401080 mov eax,dword ptr [edx] 10 00401082 push eax
11 00401083 push offset string "%d,%d\n" (0042201c) 12 00401088 call printf (004010d0) 13 0040108D add esp,0Ch
变形2_2:
printf("%d,%d\n",*ptr,*(ptr++));结果为:7,7
1 printf("%d,%d\n",*ptr,*(ptr++)); 2 0040106E mov edx,dword ptr [ebp-1Ch] ;这里没有讲执行++操作 3 00401071 mov eax,dword ptr [edx] 4 00401073 mov dword ptr [ebp-20h],eax 5 00401076 mov ecx,dword ptr [ebp-20h] 6 00401079 push ecx ;将最右边的参数压入栈
7 0040107A mov edx,dword ptr [ebp-1Ch] 8 0040107D mov eax,dword ptr [edx] 9 0040107F push eax ;将倒数第二个参数压入栈
10 00401080 push offset string "%d,%d\n" (0042201c)
11 00401085 mov ecx,dword ptr [ebp-1Ch] ;这里执行ptr = ptr + sizeof(int),但是跟printf语句没有任何冲突,可以看作是执行完printf语句后才执行的++操作 12 00401088 add ecx,4 13 0040108B mov dword ptr [ebp-1Ch],ecx 14 0040108E call printf (004010d0) 15 00401093 add esp,0Ch
变形2_3:printf("%d,%d\n",*(ptr++),*ptr);
结果为:7,7
反汇编代码同变形3相同
总结:
ps:以下个人理解,欢迎拍砖
1、一条语句中的++i,先执行++操作,才执行没有++的该语句。
1.1这里有个小不同,当++i作为参数的时候,是在要压入该参数的时候,才先执行++操作,再压入栈。
2、一条语句中的i++,先执行没有++该语句,执行完该语句在执行++操作。
2.1这里不管i++作为参数与否,都没什么变化.
便于记忆的:
“++”在变量前面,就在语句执行前执行;
“++”在变量后面,就在语句执行后执行;
特殊情况,只有++在变量前面这种有,即作为参数的时候,入栈时(汇编形式下)先++操作,再压栈.可以参考第2题
栗子1:
1 int b= 3; 2 int c; 3 c = b++ + b ++; 4 std::cout<<c <<std::endl;
结果为:6
栗子2:
1 int b= 3; 2 int c; 3 c = ++b + ++b; 4 std::cout<<c <<std::endl;
结果为:10
栗子3:
1 int b= 3; 2 int c; 3 c = b++ + ++b; // 换成 c = ++b + b++;一样的 4 std::cout<<c <<std::endl;
结果为:8