C语言中不可告人的(i++)+(i++)+(i++)!!!你发现了吗?

今天有个小学妹问我c语言中关于自增自减的问题,发现C语言的水真的深。

先看一段代码吧。

#include <stdio.h>

void main(){
	int i=5,j=5,p,q;
	p=(i++)+(i++)+(i++);      //1
	q=(++j)+(++j)+(++j);      //2
	printf("%d,%d,%d,%d",p,q,i,j);
	
} 

首先先解释p的值吧。
是不是很多在学习C语言的小伙伴觉得p应该等于18呢?

第一种:p = 15
这里写图片描述
如图中所见,在vc环境下p的值为15,那么只可能有一种解释:

p=5+5+5=15

在VC6.0中,第一个子表达式i++求完值后,其它子表达式中出现的变量i的值还没有改变,依然是5。表达式(i++) + (i++) + (i++)的值为15(5+5+5),求完值后,变量i会执行自增操作3次,其值会变成8。所以最终的结果为15和8。

第二种:p = 18

这里写图片描述
在gcc和dev c++环境下p的值为18,不难理解:

p = 5+6+7=18

由于"i++"是先加后自增,所以是从5开始边加边自增,最终的结果为18和8。

严格意义上来说,这个表达式不“合法”。严格地说C语言程序中不能出现类似的表达式,它是非法的,虽然它能通过编译系统的检查并也能输出一个结果。

再来解释下q为什么是22(TC环境下是24(8+8+8))吧。

用VC中的debug反汇编:
q=(++j)+(++j)+(++j);
0040102F mov eax,dword ptr [ebp-4] //把j的值传到寄存器EAX,dword ptr [ebp-4]存放的是变量j
00401032 add eax,1 //EAX加1
00401035 mov dword ptr [ebp-4],eax //EAX的值传到变量j,这两步实现第一个++j,此时j=6
00401038 mov ecx,dword ptr [ebp-4] //把j的值传到寄存器ECX
0040103B add ecx,1 //ECX加1
0040103E mov dword ptr [ebp-4],ecx //ECX的值传到变量j,这两步实现第二个++j,此时j=7
00401041 mov edx,dword ptr [ebp-4] //把变量j传到EDX
00401044 add edx,dword ptr [ebp-4] //再加上j的值,这一步实现了第一个加号的加法运算,内存中j变量的值仍是7
00401047 mov eax,dword ptr [ebp-4] //把j的值传到寄存器EAX
0040104A add eax,1 //EAX加1
0040104D mov dword ptr [ebp-4],eax //把EAX的值传送到变量j中,此时,变量j在内存中的值是8
00401050 add edx,dword ptr [ebp-4] //EDX加上j的值,EDX中存放的是前面的第一个加法运算的结果14,最后EDX的值为22
00401053 mov dword ptr [ebp-8],edx //把运算结果传到内存中变量q的地方,所以最后变量q为22

可能有很多小白看不太懂上述的解释

q=7+7+8=22

C语言的深水在这里就可以体现了,在C语言中,加法从左到右运算,先算前两个加数的和,再和第三个相加的过程中,他会先把前两个括号内的东西执行完成后,再执行括号外的加法,也就是(7+7)+8=22。
如果是4个++j连续的话,结果就应该是 7+7+8+9=31 。

亲爱的你们懂了吗?

ps:
在php语言中,测试上述代码:

<?php
$a = 5;
$b = 5;
$p = ($a++)+($a++)+($a++);
$q = (++$b)+(++$b)+(++$b);

echo $p;
echo $q;
echo $a;
echo $b;

这里写图片描述
得到的18和8我就不多说了,21也是比较符合我们正常思路的6+7+8。

而在python,go,以及ruby中,没有自增运算符,这样也就大大减少了这种因版本和编译器的差异导致运行结果不同的概率。

  • 23
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值