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

i++ 与 ++i 的不同

1 i=1;   printf("%d %d\n",i,i++);         //结果 2 1
2 i=1;   printf("%d %d\n",i++,i);          //结果 1 2
3 i=1;   printf("%d %d %d\n",i,i++,i);      //结果 2 1 2
4 i=1;   printf("%d %d %d %d\n",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\n",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

原文地址:https://www.cnblogs.com/cnbizhen/p/9566990.html

时间: 2024-10-15 14:09:14

printf压栈顺序之 i++ 及 ++i的相关文章

C/C++---printf/cout 从右至左压栈顺序实例详解

__cdecl压栈顺序实例 明白计算:计算是从右到左计算的 栈和寄存器变量:x++,是将计算结果存放到栈空间,最后是要出栈的:而++x和x是将计算结果直接存放到某个寄存器变量中(是同一个),所以计算完最后输出时,++x和x的结果总是相同的. ??用个小例子来说明下: int x=5; printf("%d %d\n",x,x++); int y=5; printf("%d %d\n",y++,y); int z=5; printf("%d %d %d\n&

C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)

上学期学习了汇编语言,并在操作系统实验中使用了汇编+C语言混合编程,中间也了解了一些C语言与汇编语言的对应关系. 由于汇编语言是底层的编程语言,各种函数参数都要直接控制栈进行存取,在混合编程中,要用汇编来调用C函数,当然就要知道参数的压栈情况了. 当知道C函数的参数压栈顺序是从右到左时,我觉得很奇怪,因为大多数情况下,人们的习惯是从左到右的,难不成设计者学咱们中国古代写字从右到左的习惯不成? 当时只是记下了这个规则而已,并没有去探究这其中的缘由,后来在实验中自己用汇编实现了printf和scan

函数参数的压栈顺序

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源) 先来看一道面试题: 设int arr[]={1,2,3,4 }; int *ptr=arr; printf("%d,%d",*ptr,*(++ptr)); 面试题的答案是: 2, 2 这个面试题为什么会这样呢? 原因就跟函数的压栈顺序有关,先压栈哪一个,哪一个就会被先计算,后压栈哪一个,那一个就会被后计算. 对于常见的C++程序,像缺省_cdecl或使用_stdcall的函数压栈顺序都

函数压栈顺序 -- C

基础知识: 一个程序的运行起来后,其在内存中有5个区域 1. 程序代码区 这个很简单,代码要执行,肯定要加载进内存, 我们不必关心. 2. 文字常量区 一般我们这样定义一个字符串时,其是在文字常量区的: char* s1 = "hello, world"; char* s2 = "hello, world"; if(s1 == s2) printf("s1和s2指向同一个在文字常量区的字符串"); 这里, s1和s2指向的是同一个字符串 3. 静

C: printf参数执行顺序与前置后置自增自减的影响

起源: 今天在了解副作用side-effect的过程中,看到了下面的网页,把我带到了由printf引起的一系列问题,纠结了一整天,勉强弄懂. 第一个代码没什么好解释的.而第二个printf("return of swap is %d\tx=%d,y=%d\n",swap(&x,&y),x,y)居然是"return of swap is 1 x=1,y=0",输出的x和y的值并没有改变! 原因在于C语言函数参数的处理是从右到左的压栈顺序(这个我在看第一

5-2-2 printf参数从右往左压栈

5-2-2 C中printf计算参数时是从右到左压栈的 #include <stdio.h> int main (int argc, char **argv) { int b = 3; int arr[] = {6,7,8,9,10}; int *ptr = arr; // *(ptr++) += 123; // printf ("%d,%d\n",*ptr,*(++ptr)); printf ("%d,%d\n",*ptr,*(ptr++)); ret

汇编中call printf参数压栈时错误理解

EAX, ECX,EDX,EBX均可以32bit,16bit,8bit访问,如下所示: <-------------------EAX------------------------>|<----------------------|-----------|----------->|  |<---------AX--------->|  |<---AH--->|<---AL--->| 测试代码如下: 1 .section .data 2 outp

C中prngtf是从右到左压栈的

c汇编 例子程序如下:#include <stdio.h>int main(){     int arr[] = {6,7,8,9,10};     int * ptr = arr;     *(ptr++) += 123;     printf("%d, %d\n",*ptr,*(++ptr));     return 0;}        一开始,指针ptr指向第一个元素6,见语句int *ptr = arr.接着的语句*(ptr++) += 123可以解析为:*ptr

关于函数调用压栈和返回值问题的疑惑

按照C编译器的约定调用函数时压栈的顺序是从右向左,并且返回值是保存在eax寄存器当中.这个命题本该是成立的,下面用一个小程序来反汇编观察执行过程: #include<stdio.h> int add(int x, int y){ return x+y; } int main(){ int eax=0; int z =0; int x =6; int y =5; z=add(x,y); __asm__( "movl %%eax, %0" :"+b"(eax