傻不拉几UU 发表于 2019-2-16 22:07:49

++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;

小白求助大神啦

ba21 发表于 2019-2-16 22:14:31

右至左一个一个来。
而且要在下一条语句生效。

所以这里
p=(i++)+(i++)+(i++);// 这条语句里虽然有多少i++ 但最后还是15.3*5
下新语句
temp=i //这时i也就是5 + 3 = 8,3个自增。

jackz007 发表于 2019-2-16 22:39:35

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:23:04

本帖最后由 行客 于 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

行客 发表于 2019-2-17 10:53:58

有疑问请继续跟帖。无疑问请选为最佳答案
页: [1]
查看完整版本: ++i的问题