printf出入栈详解

1. 从++i和i++说起
int main()
{
    
    
    int i = 0;
    //i++ = 100;      //编译出错: error C2106: “=”: 左操作数必须为左值
    ++i = 1;          //没有错误
    printf("%d", i);  //输出1
    return 0;
}

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

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

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


2. printf()出入栈详解
x = 1;   
printf("%d %d\n", x, x++);
x = 1;   
printf("%d %d\n", x++, x);
x = 1;   
printf("%d %d %d\n", x, x++, x);
x = 1;  
printf("%d %d %d %d\n", x, ++x, x++, x);

输出结果:

2 1
1 2
2 1 2
3 3 1 3

看到这里,你会发现,有时看起来是从左往右算,有时候是从右往左算,有时候还是从乱序算。

  1. 在处理printf()时,压栈顺序为从右往左,也就是说从右往左的计算(“计算”不等于“输出”)。

  2. 在计算时,遇到x++会记录此时的x的值作为最后的输出结果。

  3. 遇到x和++x的时候则不会将此时的计算结果作为最终的输出,只会修改x的值,在最终输出的时候都输出x的值(所以++x和x的结果总是一样的)。

原因:

  1. 对于a++的结果,是有寻址函数栈空间来记录中间结果的,在最后给printf压栈的时候,再从栈中把中间结果取出来。
  2. 对于++a的结果,则直接压寄存器变量,寄存器经过了所有的自增操作。

猜你喜欢

转载自blog.csdn.net/ssssadw/article/details/110407185
今日推荐