printf("%d,%d,%d,%d\n",i++,--i,++i,i++);编译器是如何处理的。

直接上代码:

#include <stdio.h>
int main()
{
	int i=0;
	printf("%d,%d,%d,%d\n",i++,--i,++i,i++);
	return 0;
}

你觉得上述打印结果会是什么呢?

按照变量自增自减的处理方式,后置自增或自减的返回值是通过寄存器得到的,在还没有对变量进行自增或自减时就已经将变量的值保存到了寄存器中,再结合函数自右向左的压参方式,我第一遍想到的结果是:  1  1  2  1          因为由两次后置++,如果都放在寄存器中,那么最后一次在寄存器中放的值会覆盖掉第一次在寄存器中放的值。(这是错误的理解)。

编译器运行结果:

1 2 2 0

为什么会是这样的结果呢?

要解决这个问题不得不进入到这段代码的汇编语言中进行分析,看编译器是如何处理这个函数的压参过程的,导致编译器打印出这样的结果。


这是编译器在处理printf("%d,%d,%d,%d\n",i++,--i,++i,i++);这条语句时的汇编语言。现在对这些汇编语言进行分析,看编译器都做了什么。。。。。


 printf("%d,%d,%d,%d\n",i++,--i,++i,i++); // 函数自右向左进行压参入栈
01026CB5  mov         eax,dword ptr [i]     // 将变量 i 的值放在了寄存器eax中
01026CB8  mov         dword ptr [ebp-0D0h],eax  //将eax中的值,也就是变量 i 的值放在了一块临时内存区域内。(用这个临时区域存储了i++得到的值)
01026CBE  mov         ecx,dword ptr [i]  //将变量 i 的值放在ecx中。
01026CC1  add         ecx,1                   //对ecx中的值加了1
01026CC4  mov         dword ptr [i],ecx  //将ecx中的值放在了变量 i 的存储区域中。(用经过 i++ 计算后值更新 i 的值,放在 i 的存储区域内)
01026CC7  mov         edx,dword ptr [i]  //将 i 的值放在了edx中。
01026CCA  add         edx,1                   //对edx中的值加1。

01026CCD  mov         dword ptr [i],edx  //将edx中的值存储在 i 的内存区域中,更新++i 计算后 i 的值。
01026CD0  mov         eax,dword ptr [i]  // 下面几个略去,分析方式和上面一样。
01026CD3  sub         eax,1 
01026CD6  mov         dword ptr [i],eax 
01026CD9  mov         ecx,dword ptr [i] 
01026CDC  mov         dword ptr [ebp-0D4h],ecx 
01026CE2  mov         edx,dword ptr [i] 
01026CE5  add         edx,1 
01026CE8  mov         dword ptr [i],edx 
01026CEB  mov         esi,esp 
01026CED  mov         eax,dword ptr [ebp-0D0h]  //参数的值确定好了之后,开始进行压栈操作。    将临时区域中的值放在eax中,此时这个临时区域存的是 i++ 得到的值。
01026CF3  push        eax                                     //将 i++ 的结果压栈。
01026CF4  mov         ecx,dword ptr [i]                 //到 i 的存储区域中取出 i 的值      前置++/--都是到变量自己的存储区域中取值。
01026CF7  push        ecx                                    //将 ++i 的值压栈
01026CF8  mov         edx,dword ptr [i]                //同上
01026CFB  push        edx 
01026CFC  mov         eax,dword ptr [ebp-0D4h]  //取出临时区域中的值,这个临时区域存的是 第一个参数 i++ 的值
01026D02  push        eax                                     //压栈
01026D03  push        102CCBCh 
01026D08  call        dword ptr ds:[10303A4h] 
01026D0E  add         esp,14h 
01026D11  cmp         esi,esp 
01026D13  call        __RTC_CheckEsp (010212D0h) 


由以上汇编代码的解释你应该可以理解为什么会打印出 1 2 2 0的结果了吧。。。。

总结:

一个函数的参数是变量的多次自增自减,那么编译器在处理的时候,对函数的参数自左向右处理,将后置++/--的值放在了一个临时区域内(而不是用寄存器存),然后再到变量真正的存储区域进行+1/-1。 将前置++/--的值直接经过计算将结果存入到变量的存储区域内。

  • 14
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值