鱼C论坛

 找回密码
 立即注册
查看: 3301|回复: 4

++i的问题

[复制链接]
发表于 2019-2-16 22:07:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一个老问题了,但是还是有点不太懂
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;

小白求助大神啦
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-2-16 22:14:31 | 显示全部楼层
右至左一个一个来。
而且要在下一条语句生效。

所以这里
p=(i++)+(i++)+(i++);  // 这条语句里虽然有多少i++ 但最后还是15.3*5
下新语句
temp=i //这时i也就是5 + 3 = 8,3个自增。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-16 22:39:35 | 显示全部楼层
  1. p = (i ++) + (i ++) + (i ++)    ;
复制代码

等效于
  1. p = i + (i + 1) + (i + 2)       ;
  2. i += 3                          ;
复制代码


  1. q = (++ j) + (++ j) + (++ j)    ;
复制代码

等效于
  1. q = (j + 1) + (j + 2) + (j + 3) ;
  2. j += 3                          ;
复制代码


小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-17 10:23:04 | 显示全部楼层
本帖最后由 行客 于 2019-2-17 10:51 编辑

首先声明一下,不同编译器下的处理结果可能是有不同的,这里以VC6下分析为例:

p=(i++)+(i++)+(i++);
执行完当前语句后,
在VC6下,首先很确定的告诉你p的值为15。从汇编代码我们先看下分析:
  1. 10:       p=(i++)+(i++)+(i++);  //括号内的i是同步加吗? 3个i++同时吗,如果3个括号同步算的话,结果应该是5+5+5,输入i=6,P=15。如果区分右侧优先级,应该是5 +6+7 ,最后输入I结果应该是8。P=18.
  2. 0040D796   mov         eax,dword ptr [ebp-4]                                ;dword ptr [ebp-4]即为局部变量i,这里将i的值传送到eax
  3. 0040D799   add         eax,dword ptr [ebp-4]                                ;将eax和i相加,并将结果放到eax
  4. 0040D79C   add         eax,dword ptr [ebp-4]                                ;将eax和i再次相加,并将结果放到eax
  5. 0040D79F   mov         dword ptr [ebp-0Ch],eax                        ;将eax的值传送到dword ptr [ebp-0Ch],即p。此时i没有变化,依然为5,p的结果为5。
  6. 0040D7A2   mov         ecx,dword ptr [ebp-4]                                ;以下开始计算i的变化:将dword ptr [ebp-4]即为局部变量i的值传送到ecx
  7. 0040D7A5   add         ecx,1                                                        ;将ecx的值加1
  8. 0040D7A8   mov         dword ptr [ebp-4],ecx                                ;以下相同
  9. 0040D7AB   mov         edx,dword ptr [ebp-4]
  10. 0040D7AE   add         edx,1
  11. 0040D7B1   mov         dword ptr [ebp-4],edx
  12. 0040D7B4   mov         eax,dword ptr [ebp-4]
  13. 0040D7B7   add         eax,1
  14. 0040D7BA   mov         dword ptr [ebp-4],eax                                ;最终将计算后的eax传值给dword ptr [ebp-4],即i。i值此时为8
复制代码

通过以上汇编代码分析,我们可以很清楚的看到:i++的后加加,是在执行完其他运算并赋值给p后,再做的后自增变化。
这里也印证了:后加加,就是先用这个变量,然后再用这个变量做自增。

那么,
q=(++j)+(++j)+(++j);
就很好理解了。应该是先自增完,再计算呗。
也就印证了:前加加,就是先加,然后才用这个变量。这个理解,应该是正常的、标准的理解。
但是,但是,但是还真有点变化。。。VC6下q的值的结果竟然为,22!这到底为什么
为了便于理解,还是先看下汇编代码:
  1. 12:       q=(++j)+(++j)+(++j);  //同上
  2. 0040D7BD   mov         ecx,dword ptr [ebp-8]                                ;dword ptr [ebp-8]即变量j
  3. 0040D7C0   add         ecx,1                                                         ;我们清楚的看到,是先增1,j结果为6
  4. 0040D7C3   mov         dword ptr [ebp-8],ecx
  5. 0040D7C6   mov         edx,dword ptr [ebp-8]
  6. 0040D7C9   add         edx,1                                                         ;我们清楚的看到,再增1,j结果为7
  7. 0040D7CC   mov         dword ptr [ebp-8],edx                               
  8. 0040D7CF   mov         eax,dword ptr [ebp-8]
  9. 0040D7D2   add         eax,dword ptr [ebp-8]                                ;但是这里很奇怪,开始计算j+j了,这时eax为14。
  10. 0040D7D5   mov         ecx,dword ptr [ebp-8]                                ;这里开始又将j传值给ecx
  11. 0040D7D8   add         ecx,1                                                        ;ecx自增1
  12. 0040D7DB   mov         dword ptr [ebp-8],ecx                                ;ecx传递给j,j的值变成8了。
  13. 0040D7DE   add         eax,dword ptr [ebp-8]                                ;计算eax的14加j的8,结果22传给eax。
  14. 0040D7E1   mov         dword ptr [ebp-10h],eax                        ;最终q的值为22。
复制代码

j的值运算结束后为8好理解,这个没什么理解方面的问题。但是q的值为什么会这么特殊,这样计算?
原因是:不同的编译器,生产的代码不一样,导致的结果也会不一样。或者说,这种计算结果,只单纯从C的角度去思考根本就想不明白,是因为这个根本就没有什么道理和标准,甚至对于编译器来讲,或许这就算是一个BUG。所以,我一直不建议搞什么特别长的、连续使用的复杂的++或者--,你自己写程序为的是一个正确的运行结果,非要把程序写的自己都难以理解有意义吗?
当年我们很多的教科书中,在这个地方来回的折腾,来回的讲,搞的大家晕晕乎乎,其实一点价值都没有。所有,有某教授的C语言教材,一直被人吐槽。

为了说明不同编译器下,结果会不一样,我们可以再继续做以下测试:
我们简化代码为:
  1. #include <stdio.h>
  2. void main()
  3. {
  4. int j = 5;
  5. int q;
  6. q =(++j)+(++j)+(++j);
  7. }
复制代码


环境:win7

编译器:GCC

IDE:vc++6.0  /DEV-C++

结果:q = 22
  1. 6:    q =(++j)+(++j)+(++j);
  2. 00401036   mov         eax,dword ptr [ebp-8]           移动J=5到寄存器eax内
  3. 00401039   add         eax,1                                       在寄存器eax值上加1,eax=6
  4. 0040103C   mov         dword ptr [ebp-8],eax          把寄存器的值移动到变量j上去,j= 6
  5. 0040103F   mov         ecx,dword ptr [ebp-8]           移动J=6到寄存器ecx
  6. 00401042   add         ecx,1                                       在寄存器上ecx+1,j=6
  7. 00401045   mov         dword ptr [ebp-8],ecx          把寄存器ecx上的值移到J上去,J=7
  8. 00401048   mov         edx,dword ptr [ebp-8]         把J=7移动到寄存器edx=7
  9. 0040104B   add         edx,dword ptr [ebp-8]          edx值+j  此时j=7,edx=7+7
  10. 0040104E   mov         eax,dword ptr [ebp-8]          把j=7Move给 第一个寄存器eax
  11. 00401051   add         eax,1                                       eax再加1,此时寄存器eax=8
  12. 00401054   mov         dword ptr [ebp-8],eax          把此时的eax的值move给 j=8
  13. 00401057   add         edx,dword ptr [ebp-8]           edx值= edx+j = 14+8
  14. 0040105A   mov         dword ptr [ebp-0Ch],edx      edx值 move给 j = 22
复制代码




环境:win7

编译器:GCC

IDE: VC++ 2008

运行结果:24
  1. q =(++j)+(++j)+(++j);
  2. 003A1815  mov         eax,dword ptr [j]   //eax = 5,j = 5
  3. 003A1818  add         eax,1   //eax = 6
  4. 003A181B  mov         dword ptr [j],eax  j = 6
  5. 003A181E  mov         ecx,dword ptr [j]  ecx = 6
  6. 003A1821  add         ecx,1  ecx = 7
  7. 003A1824  mov         dword ptr [j],ecx  j = 7
  8. 003A1827  mov         edx,dword ptr [j]   edx = 7
  9. 003A182A  add         edx,1   edx = 8
  10. 003A182D  mov         dword ptr [j],edx   j = 8
  11. 003A1830  mov         eax,dword ptr [j] eax = 8
  12. 003A1833  add         eax,dword ptr [j] eax = 16
  13. 003A1836  add         eax,dword ptr [j]  eax = 24
  14. 003A1839  mov         dword ptr [q],eax
复制代码

评分

参与人数 1荣誉 +1 鱼币 +1 收起 理由
wjp + 1 + 1 学到了

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-17 10:53:58 | 显示全部楼层
有疑问请继续跟帖。无疑问请选为最佳答案
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-17 07:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表