2015-04-03 66 views
2

我試圖與海灣合作委員會的作用__builtin_return_address發揮,以瞭解運行時數據結構的一些基本概念,所以請原諒我,如果我問一個完全的新手和愚蠢的問題:如何使用__builtin_return_address()遞歸?

我的測試代碼是這樣的

#include <stdio.h> 

void a(int i) 
{ 
    if (i>0) { 
     printf("The return address is %p\n", __builtin_return_address(0)); 
     a(--i); 
    } 
    else 
     return; 
} 
int main() 
{ 
    a(10); 
    return 0; 
} 

,輸出是

The return address is 0x4005ee 
The return address is 0x4005db 
The return address is 0x4005db 
The return address is 0x4005db 
The return address is 0x4005db 
... 

所以我的問題是,爲什麼這些遞歸調用函數的返回地址同樣喜歡他們都回到頂層調用者?它們不應該像「遞歸直接調用者」一樣嗎?

謝謝。

+1

因爲雖然每個函數調用的框架是有史以來進一步降低堆棧,函數調用的每個實例都執行相同的_code_,返回地址是指令的地址函數'a()'的_code_緊跟在'call'指令後面給'a()'本身。要查看穩定減少的地址,請在函數的框架中輸出局部變量的地址,例如'&i'。 – 2015-04-03 18:44:44

+0

這看起來很像尾遞歸優化。嘗試編譯所有優化的代碼 - 例如使用'-O0',這可能會阻止優化發生,從而產生你期望的結果。 – Petesh 2015-04-03 18:45:17

+0

@Petesh,它看起來沒有任何優化。我之前也嘗試過-O0,因爲我也懷疑它。但顯然它沒有改變任何東西... – Peng 2015-04-03 23:02:41

回答

2
f5 f4 f3 f2 f1 a(5) --> f5 
f5 f4 f3 f2 f1 a(5) a(4) --> f3 
f5 f4 f3 f2 f1 a(5) a(4) a(3) --> f1 
f5 f4 f3 f2 f1 a(5) a(4) a(3) a(2) --> a(4) 
f5 f4 f3 f2 f1 a(5) a(4) a(3) a(2) a(1) --> a(2) 

不要在遞歸期間改變索引!

f5 f4 f3 f2 f1 a(5) --> f5 
f5 f4 f3 f2 f1 a(5) a(5) --> f4 

站上ret_add(i) == ret_add(0)

+0

避免無用的遞歸,這裏更喜歡while/loop! 'while(i> 0){printf(「返回地址是%p \ n」,__builtin_return_address(i--)); }' – 2017-10-09 10:33:03