zoukankan      html  css  js  c++  java
  • 关于C语言的printf输出问题

    前端面试的时候老总居然问这个问题,有点震惊……

    #include <stdio.h>
    #include <stdlib.h>
    void main() {
        int i = 1;
        printf("%d,%d,%d,%d,%d,%d
    ", i,i++,++i,i--,i++,--i);
        system("pause");
    }

    作为一个以前压根没深入研究过C语言运行机制的人,这个问题真是难住我了

    如果你的回答是输出

    1,1,3,3,2,2

    恭喜你跟我错得一样,老总说这跟语言没关系,所有语言的思路都一样……但是明明JS的运行结果就是上面那个嘛……

    在VS下,运行结果是

    2,1,2,1,0,2

    震惊之余,看了下反汇编的代码

        int i = 1;
    00DF3C0E  mov         dword ptr [i],1  
        printf("%d,%d,%d,%d,%d,%d
    ", i,i++,++i,i--,i++,--i);//看看结果是从右往左开始运算
    00DF3C15  mov         eax,dword ptr [i]  
    00DF3C18  sub         eax,1  
    00DF3C1B  mov         dword ptr [i],eax //--i,i=0
    00DF3C1E  mov         ecx,dword ptr [i]  
    00DF3C21  mov         dword ptr [ebp-0D0h],ecx //将i复制一份到 dword ptr [ebp-0D0h]这个地址,0
    00DF3C27  mov         edx,dword ptr [i]  
    00DF3C2A  add         edx,1  
    00DF3C2D  mov         dword ptr [i],edx  //i++,i=1
    00DF3C30  mov         eax,dword ptr [i]  
    00DF3C33  mov         dword ptr [ebp-0D4h],eax //将i复制一份到 dword ptr [ebp-0D4h]这个地址,1
    00DF3C39  mov         ecx,dword ptr [i]  
    00DF3C3C  sub         ecx,1  
    00DF3C3F  mov         dword ptr [i],ecx  //i--,i=0
    00DF3C42  mov         edx,dword ptr [i]  
    00DF3C45  add         edx,1  
    00DF3C48  mov         dword ptr [i],edx  //++i,i=1
    00DF3C4B  mov         eax,dword ptr [i]  
    00DF3C4E  mov         dword ptr [ebp-0D8h],eax //将结果复制一份到dword ptr [ebp-0D8h]这个地址,1
    00DF3C54  mov         ecx,dword ptr [i]  
    00DF3C57  add         ecx,1  
    00DF3C5A  mov         dword ptr [i],ecx  //i++,i=2
    00DF3C5D  mov         esi,esp  
    00DF3C5F  mov         edx,dword ptr [i]  //edx = 2
    00DF3C62  push        edx  //2入
    00DF3C63  mov         eax,dword ptr [ebp-0D0h] //eax = 0
    00DF3C69  push        eax  //0入
    00DF3C6A  mov         ecx,dword ptr [ebp-0D4h] //ecx = 1
    00DF3C70  push        ecx  //1入
    00DF3C71  mov         edx,dword ptr [i]  //edx = 2
    00DF3C74  push        edx  //2入
    00DF3C75  mov         eax,dword ptr [ebp-0D8h]  //eax = 1
    00DF3C7B  push        eax  //1入
    00DF3C7C  mov         ecx,dword ptr [i]  //ecx = 2
    00DF3C7F  push        ecx  //2入
    00DF3C80  push        0DF59CCh  
    00DF3C85  call        dword ptr ds:[0DF9114h]  
    00DF3C8B  add         esp,1Ch  
    00DF3C8E  cmp         esi,esp  
    00DF3C90  call        __RTC_CheckEsp (0DF1136h)  

     虽然其中部分操作不知道是做什么用的,但是看最下面的数字,可以发现就是最终的输出结果

    从其中可以分析出,在运算过程中,往内存中写入了多个新的值(比如新产生的dword ptr [ebp-0D0h])

    碰到i++,i--的时候,会从一个新的内存地址中取值

    碰到++i,--i,i的时候,会从最初的内存地址中取值,也就是获取i计算的最终值

    那么,我们可以发现,在计算i++,i--之前,i的结果会缓存到内存中,以便后面使用

    这样,结果就迎刃而解了

    PS:

    运算是自右往左的方向计算的,压栈也是

    如果我们在最后面再加一个参数i,会发现反汇编的代码最开始的部分没变,也就是说,首先会计算自增,自减部分

    如果在其中加入i+1这样的操作,会发现这部分代码是在压栈的同时计算的

  • 相关阅读:
    【JDBC】JDBC实战
    【JDBC】JDBC操作实战
    【Oracle】事务、表复制
    Hibernate 再接触 继承映射
    Hibernate 再接触 集合映射
    Hibernate 再接触 CRUD
    Hibernate 再接触 多对多单向双向关联
    Hibernnate 一对多多对一双向关联
    Hibernate 再接触 一对多单向关联
    Hibernate 再接触 多对一与一对多
  • 原文地址:https://www.cnblogs.com/strayling/p/3843494.html
Copyright © 2011-2022 走看看