2015-02-06 39 views
9

gcc documentation包含以下內容:函數定義之前的調用不能被內聯?

當一個函數內聯和靜態的,如果對 函數的所有調用都集成到調用,而該函數的地址是 從未使用過,那麼該函數自身的彙編代碼從未被 引用。在這種情況下,GCC實際上不會爲該函數輸出彙編代碼 ,除非您指定選項 -fkeep-inline-functions。由於各種原因,某些呼叫不能被集成(特別是,調用之前函數的定義 不能被集成,並且都不能在 定義內的遞歸調用)。

這對我來說總是很荒謬 - 爲什麼現代編譯器會變得愚蠢?經過快速測試,它確實看起來不真實。

測試代碼:

static inline int foo(); 

int bar() { 
    return foo(); 
} 

int foo() { 
    return 42; 
} 

Linux上的GCC-4.9.2結果對於foo()bar()代碼,但沒有。你可以看到,foo()已經整合:

bar: 
.LFB0: 
    .cfi_startproc 
    movl $42, %eax 
    ret 
    .cfi_endproc 

如果我編譯爲C++的結果是一樣的,只是名字改編。

與文檔相反,儘管foo()bar()調用後定義,foo()已完全集成到bar()中。

我誤解了文檔還是不正確?也許這是更正確的一些更復雜的情況?

我不知道「集成」和「內聯」之間是否存在技術上的區別,但我懷疑「集成」用於區分關鍵字inline,它只是指函數內聯(因此標題)。

這個問題被標記爲C和C++,因爲這部分的gcc文檔屬於「C語言家族」,我期望兩種語言的答案是相同的。

+5

該句已存在於gcc 3.0.4文檔中。他們可能會增強編譯器而不修改文檔。 – AProgrammer 2015-02-06 12:40:39

+0

是的。它似乎不符合實際發生的情況。儘管如此,我也在4.8.1上嘗試過 - 同樣的行爲。 – SGrebenkin 2015-02-06 12:43:16

+3

甚至在gcc 2.95.3文檔中。 – Praxeolitic 2015-02-06 12:44:01

回答

7

在解析下一個函數之前,一旦GCC被解析,Gcc就會一次編譯和優化一個函數。 IIRC,它只是在4.X時間框架中引入了-funit-at-a-time選項,該選項在讀完整個編譯單元之後推遲優化,然後等待一些版本以默認啓用它。

電話後定義內聯函數的可能性可能已經被引入作爲-funit-at-a-time工作的一部分,並且內嵌的文檔(提有關定義日期前至少可以追溯到2.95通話)還沒有更新呢。

相關問題