首頁  >  問答  >  主體

java - C,C++函数调用时入栈顺序 是编译时还是运行时完成的?

我的理解是静态编译时,因为C语言是过程性语言只能静态联编不能动态联编,而C++编译于此类似,所以是编译时完全。不知道这样对不对?

天蓬老师天蓬老师2763 天前803

全部回覆(3)我來回復

  • 阿神

    阿神2017-04-18 10:50:16

    入棧的順序是編譯時決定的。

    函數呼叫之前需要入棧的主要是函數參數,而參數都是固定的(可變參數只是用巨集確定偏移量)。
    呼叫函數的程式碼是放在程式碼段的,入棧都是以指令方式進行的,所以順序都是編譯時決定的。

    回覆
    0
  • 阿神

    阿神2017-04-18 10:50:16

    @lianera 說的不錯,入棧的順序是編譯時決定的。

    我這給你看個例子:
    我有段程式碼是這樣的

    #include <stdio.h>
    
    int test_fun(int a, int b)
    {
        return a + b;    
    }
    
    int main(int argc, char *argv[])
    {
        int A, B, ret;
    
        A = 3;
        B = 4;
        ret = test_fun(A, B);
    
        return 1;
    }

    編譯後,他的彙編程式碼是這樣的

    int test_fun(int a, int b)
    {
      400474:    55                       push   %rbp
      400475:    48 89 e5                 mov    %rsp,%rbp
      // $edi存的是A的值,$esi存的是B的值,将他们压入栈中
      400478:    89 7d fc                 mov    %edi,-0x4(%rbp)
      40047b:    89 75 f8                 mov    %esi,-0x8(%rbp)
        return a + b;    
      40047e:    8b 45 f8                 mov    -0x8(%rbp),%eax
      400481:    8b 55 fc                 mov    -0x4(%rbp),%edx
      400484:    8d 04 02                 lea    (%rdx,%rax,1),%eax
    }
    
    int main(int argc, char *argv[])
    {
      400489:    55                       push   %rbp
      40048a:    48 89 e5                 mov    %rsp,%rbp
      40048d:    48 83 ec 20              sub    rrreeex20,%rsp
      400491:    89 7d ec                 mov    %edi,-0x14(%rbp)
      400494:    48 89 75 e0              mov    %rsi,-0x20(%rbp)
        int A, B, ret;
      
      // 压入本地变量A
        A = 3;
      400498:    c7 45 f4 03 00 00 00     movl   rrreeex3,-0xc(%rbp)
      // 压入本地变量B
        B = 4;
      40049f:    c7 45 f8 04 00 00 00     movl   rrreeex4,-0x8(%rbp)
        ret = test_fun(A, B);
      4004a6:    8b 55 f8                 mov    -0x8(%rbp),%edx
      4004a9:    8b 45 f4                 mov    -0xc(%rbp),%eax
      // 将A和B的值放入相应的寄存器
      4004ac:    89 d6                    mov    %edx,%esi
      4004ae:    89 c7                    mov    %eax,%edi
      // 调用test_fun
      4004b0:    e8 bf ff ff ff           callq  400474 <test_fun>
      4004b5:    89 45 fc                 mov    %eax,-0x4(%rbp)
    
        return 1;
      4004b8:    b8 01 00 00 00           mov    rrreeex1,%eax
    }
    

    不懂彙編也沒關係,在編譯過程中,參數的傳遞順序,參數、本地變數等應該放在堆疊的哪個位置(相對位置)都是定了的。當程式運行到對應程式後會按照編譯好的順序對堆疊進行操作。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-18 10:50:16

    入棧這個不是運作時才有的過程嗎?編譯只是翻譯為字節碼的過程,為什麼會有入棧?

    回覆
    0
  • 取消回覆