关于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

posted @ 2012-08-23 15:55  xiaolongxia  阅读(196)  评论(0)    收藏  举报