一、++i与i++的规则
初学编程的人,对于++i与i++老是傻傻分不清,甚至有一定开发经验的人也会栽倒在这两个表达式上。大家看下面两个例子:
例1:代码如下,这是个比较简单的例子,对于表达式j=i++;等同于"j=i;i=i+1;",而对于表达式k=i++;等同于"i=i+1;k=i;",所以最后的执行结果是:i=2,j=0,k=2。
int i=0,j,k;
j=i++;
k=++i;
printf("i=%d,j=%d,k=%d\n",i,j,k);
例2:上例的用法很常见,这个例子就有点麻烦了,如果不能从根本上理解++i和i++,可能就会出错了。
int i=0,j;
j=(i++)+(++i)+(i++)+(++i)+(i++)+(++i);
printf("%d,%d\n",i,j);
‘'j=(i++)+(++i)+(i++)+(++i)+(i++)+(++i);"中有3组“++i”,有3组“i++”。所以代码等同于
int i=0,j;
// 先处理++i
i=i+1;
i=i+1;
i=i+1;
//执行语句,++i和i++都替换成i
j=i+i+i+i+i+i;
// 处理i++
i=i+1;
i=i+1;
i=i+1;
printf("i=%d,j=%d\n",i,j);
所以,该例最终结果是"i=6,j=18"
从上述例子中我们假设"语句A"含有n个“++i”和m个“i++”;则"语句A"就等同于
// 执行n次i=i+1
i=i+1;
.....
//将"语句A"中的++i和i++都替换成i
语句A
// 执行m次i=i+1
i=i+1;
.....
二、通过反汇编语言验证
我们使用Vs2017的反汇编验证一下例1
j = i++;
/*等同于j=i*/
00007FF65B8E5771 mov eax,dword ptr [i] // 将变量i的数据导入寄存器eax
00007FF65B8E5774 mov dword ptr [j],eax // 将寄存器eax的数据导出到变量j
/*等同于i=i+1*/
00007FF65B8E5777 mov eax,dword ptr [i] // 将i的数据导入寄存器eax
00007FF65B8E577A inc eax // 将寄存器eax累加1
00007FF65B8E577C mov dword ptr [i],eax // 将寄存器eax的数据导出到变量i
k = ++i;
/*等同于i=i+1*/
00007FF65B8E577F mov eax,dword ptr [i] // 将i的数据导入寄存器eax
00007FF65B8E5782 inc eax // 将寄存器eax累加1
00007FF65B8E5784 mov dword ptr [i],eax // 将寄存器eax的数据导出到变量i
/*等同于k=i*/
00007FF65B8E5787 mov eax,dword ptr [i] // 将变量i的数据导入寄存器eax
00007FF65B8E578A mov dword ptr [k],eax // 将寄存器eax的数据导出到变量k
我们使用Vs2017的反汇编验证一下例2
j = (i++)+ (++i)+(i++) + (++i) + (i++) + (++i) ;
/*等同于i=i+1*/
00007FF65CD35771 mov eax,dword ptr [i]
00007FF65CD35774 inc eax
00007FF65CD35776 mov dword ptr [i],eax
/*等同于i=i+1*/
00007FF65CD35779 mov eax,dword ptr [i]
00007FF65CD3577C inc eax
00007FF65CD3577E mov dword ptr [i],eax
/*等同于i=i+1*/
00007FF65CD35781 mov eax,dword ptr [i]
00007FF65CD35784 inc eax
00007FF65CD35786 mov dword ptr [i],eax
/*等同于j=i+i+i+i+i+i;*/
00007FF65CD35789 mov eax,dword ptr [i] // 将i的数据导入寄存器eax
00007FF65CD3578C mov ecx,dword ptr [i] // 将i的数据导入寄存器ecx
00007FF65CD3578F add ecx,eax // ecx=ecx+eax=i+i
00007FF65CD35791 mov eax,ecx // eax=ecx=i+i
00007FF65CD35793 add eax,dword ptr [i] // eax=eax+i
00007FF65CD35796 add eax,dword ptr [i] // eax=eax+i
00007FF65CD35799 add eax,dword ptr [i] // eax=eax+i
00007FF65CD3579C add eax,dword ptr [i] // eax=eax+i
00007FF65CD3579F mov dword ptr [j],eax // 将寄存器eax的数据导出到变量j
/*等同于i=i+1*/
00007FF65CD357A2 mov eax,dword ptr [i]
00007FF65CD357A5 inc eax
00007FF65CD357A7 mov dword ptr [i],eax
/*等同于i=i+1*/
00007FF65CD357AA mov eax,dword ptr [i]
00007FF65CD357AD inc eax
00007FF65CD357AF mov dword ptr [i],eax
/*等同于i=i+1*/
00007FF65CD357B2 mov eax,dword ptr [i]
00007FF65CD357B5 inc eax
00007FF65CD357B7 mov dword ptr [i],eax