++i的问题
一个老问题了,但是还是有点不太懂int i = 5,j=5,p,q;
p=(i++)+(i++)+(i++);//括号内的i是同步加吗? 3个i++同时吗,如果3个括号同步算的话,结果应该是5+5+5,输入i=6,P=15。如果区分右侧优先级,应该是5 +6+7 ,最后输入I结果应该是8。P=18.
q=(++j)+(++j)+(++j);//同上
输入 p q i j;
小白求助大神啦 右至左一个一个来。
而且要在下一条语句生效。
所以这里
p=(i++)+(i++)+(i++);// 这条语句里虽然有多少i++ 但最后还是15.3*5
下新语句
temp=i //这时i也就是5 + 3 = 8,3个自增。 p = (i ++) + (i ++) + (i ++) ;
等效于
p = i + (i + 1) + (i + 2) ;
i += 3 ;
而
q = (++ j) + (++ j) + (++ j) ;
等效于
q = (j + 1) + (j + 2) + (j + 3) ;
j += 3 ;
本帖最后由 行客 于 2019-2-17 10:51 编辑
首先声明一下,不同编译器下的处理结果可能是有不同的,这里以VC6下分析为例:
p=(i++)+(i++)+(i++);
执行完当前语句后,
在VC6下,首先很确定的告诉你p的值为15。从汇编代码我们先看下分析:
10: p=(i++)+(i++)+(i++);//括号内的i是同步加吗? 3个i++同时吗,如果3个括号同步算的话,结果应该是5+5+5,输入i=6,P=15。如果区分右侧优先级,应该是5 +6+7 ,最后输入I结果应该是8。P=18.
0040D796 mov eax,dword ptr ;dword ptr 即为局部变量i,这里将i的值传送到eax
0040D799 add eax,dword ptr ;将eax和i相加,并将结果放到eax
0040D79C add eax,dword ptr ;将eax和i再次相加,并将结果放到eax
0040D79F mov dword ptr ,eax ;将eax的值传送到dword ptr ,即p。此时i没有变化,依然为5,p的结果为5。
0040D7A2 mov ecx,dword ptr ;以下开始计算i的变化:将dword ptr 即为局部变量i的值传送到ecx
0040D7A5 add ecx,1 ;将ecx的值加1
0040D7A8 mov dword ptr ,ecx ;以下相同
0040D7AB mov edx,dword ptr
0040D7AE add edx,1
0040D7B1 mov dword ptr ,edx
0040D7B4 mov eax,dword ptr
0040D7B7 add eax,1
0040D7BA mov dword ptr ,eax ;最终将计算后的eax传值给dword ptr ,即i。i值此时为8
通过以上汇编代码分析,我们可以很清楚的看到:i++的后加加,是在执行完其他运算并赋值给p后,再做的后自增变化。
这里也印证了:后加加,就是先用这个变量,然后再用这个变量做自增。
那么,
q=(++j)+(++j)+(++j);
就很好理解了。应该是先自增完,再计算呗。
也就印证了:前加加,就是先加,然后才用这个变量。这个理解,应该是正常的、标准的理解。
但是,但是,但是还真有点变化。。。VC6下q的值的结果竟然为,22!这到底为什么
为了便于理解,还是先看下汇编代码:
12: q=(++j)+(++j)+(++j);//同上
0040D7BD mov ecx,dword ptr ;dword ptr 即变量j
0040D7C0 add ecx,1 ;我们清楚的看到,是先增1,j结果为6
0040D7C3 mov dword ptr ,ecx
0040D7C6 mov edx,dword ptr
0040D7C9 add edx,1 ;我们清楚的看到,再增1,j结果为7
0040D7CC mov dword ptr ,edx
0040D7CF mov eax,dword ptr
0040D7D2 add eax,dword ptr ;但是这里很奇怪,开始计算j+j了,这时eax为14。
0040D7D5 mov ecx,dword ptr ;这里开始又将j传值给ecx
0040D7D8 add ecx,1 ;ecx自增1
0040D7DB mov dword ptr ,ecx ;ecx传递给j,j的值变成8了。
0040D7DE add eax,dword ptr ;计算eax的14加j的8,结果22传给eax。
0040D7E1 mov dword ptr ,eax ;最终q的值为22。
j的值运算结束后为8好理解,这个没什么理解方面的问题。但是q的值为什么会这么特殊,这样计算?
原因是:不同的编译器,生产的代码不一样,导致的结果也会不一样。或者说,这种计算结果,只单纯从C的角度去思考根本就想不明白,是因为这个根本就没有什么道理和标准,甚至对于编译器来讲,或许这就算是一个BUG。所以,我一直不建议搞什么特别长的、连续使用的复杂的++或者--,你自己写程序为的是一个正确的运行结果,非要把程序写的自己都难以理解有意义吗?
当年我们很多的教科书中,在这个地方来回的折腾,来回的讲,搞的大家晕晕乎乎,其实一点价值都没有。所有,有某教授的C语言教材,一直被人吐槽。
为了说明不同编译器下,结果会不一样,我们可以再继续做以下测试:
我们简化代码为:
#include <stdio.h>
void main()
{
int j = 5;
int q;
q =(++j)+(++j)+(++j);
}
环境:win7
编译器:GCC
IDE:vc++6.0/DEV-C++
结果:q = 22
6: q =(++j)+(++j)+(++j);
00401036 mov eax,dword ptr 移动J=5到寄存器eax内
00401039 add eax,1 在寄存器eax值上加1,eax=6
0040103C mov dword ptr ,eax 把寄存器的值移动到变量j上去,j= 6
0040103F mov ecx,dword ptr 移动J=6到寄存器ecx
00401042 add ecx,1 在寄存器上ecx+1,j=6
00401045 mov dword ptr ,ecx 把寄存器ecx上的值移到J上去,J=7
00401048 mov edx,dword ptr 把J=7移动到寄存器edx=7
0040104B add edx,dword ptr edx值+j此时j=7,edx=7+7
0040104E mov eax,dword ptr 把j=7Move给 第一个寄存器eax
00401051 add eax,1 eax再加1,此时寄存器eax=8
00401054 mov dword ptr ,eax 把此时的eax的值move给 j=8
00401057 add edx,dword ptr edx值= edx+j = 14+8
0040105A mov dword ptr ,edx edx值 move给 j = 22
环境:win7
编译器:GCC
IDE: VC++ 2008
运行结果:24
q =(++j)+(++j)+(++j);
003A1815mov eax,dword ptr //eax = 5,j = 5
003A1818add eax,1 //eax = 6
003A181Bmov dword ptr ,eaxj = 6
003A181Emov ecx,dword ptr ecx = 6
003A1821add ecx,1ecx = 7
003A1824mov dword ptr ,ecxj = 7
003A1827mov edx,dword ptr edx = 7
003A182Aadd edx,1 edx = 8
003A182Dmov dword ptr ,edx j = 8
003A1830mov eax,dword ptr eax = 8
003A1833add eax,dword ptr eax = 16
003A1836add eax,dword ptr eax = 24
003A1839mov dword ptr ,eax 有疑问请继续跟帖。无疑问请选为最佳答案
页:
[1]