printf压栈顺序之 i++ 及 ++i

Posted cnbizhen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了printf压栈顺序之 i++ 及 ++i相关的知识,希望对你有一定的参考价值。

i++ 与 ++i 的不同

1 i=1;   printf("%d %d
",i,i++);         //结果 2 1
2 i=1;   printf("%d %d
",i++,i);          //结果 1 2
3 i=1;   printf("%d %d %d
",i,i++,i);      //结果 2 1 2
4 i=1;   printf("%d %d %d %d
",i,++i,i++,i);  //结果 3 3 1 3

解析:

已知前提:

  1. printf输出时,压栈顺序为从右往左,也就是说从右往左的计算;
  2. 入栈时先进后出,先进入的在栈的高地址,后进入的在栈的低地址;
  3. printf后面的表达式,比如i++, 此操作为计算,”计算“ 是计算,但是不等于“输出”的结果;
  4. i++的结果,是有ebp寻址函数栈空间来记录中间结果的,在最后给printf压栈的时候,再从ebp栈中把中间结果取出来压入printf分配的栈中;
  5. ++i的结果,是直接寄存器进行自增操作,然后把该寄存器的地址压入printf分配的栈中。

 

i++是先计算后自加,而++i是先自加后计算。

1 int  main()
2 {
3     int i = 0;
4     //i++ = 100;//直接报错,编译出错: error C2106: “=”: 左操作数必须为左值
5     ++i=100;//通过,没有错误
6     printf("%d", i);//直接打印100
7     return 0;
8 }

  从上面的代码情况可以认为编译器在处理i++和++i的方式不同

  1. i++完成之后返回的是右值也就是一个常量
  2. ++i完成之后返回的是左值也就是i的内存,对++i赋值相当于给i赋值

  结论:printf压栈的时候,i++其实压的是ebr中间结果的值,也就是一个常量。而++i 因为计算后的结果是一个左值,故会将i对应的地址进行压栈。

 

例题说明

i=1;   printf("%d %d %d %d
",i,++i,i++,i);  //结果 3 3 1 3

++i 是直接真值进行自加,而 i++ 则是通过在ebr中存放的临时副本进行加1后再赋值给i

运算式 真值(寄存器中) 副本(ebr中)
低位 i 3  
  ++i 3  
  i++ 2 1
高位 i 1  

最终 i 的真值为3,i++ 的ebr定值为1, 故最后的输出结果为:3 3 1 3

参考:链接1链接2链接3

 

以上是关于printf压栈顺序之 i++ 及 ++i的主要内容,如果未能解决你的问题,请参考以下文章

代码混淆之道——控制流扁平与不透明谓词理论篇

玩转matlab之一维 gauss 数值积分公式及matlab源代码

数值计算方法实验之按照按三弯矩方程及追赶法的三次样条插值 (MATLAB 代码)

在二维数组中以之字形顺序打印数字

MFC单文档视图之图标资源加载及绘制

for循环执行顺序