2016-05-10 63 views
3

一位朋友寫了一個函數,大約有300行代碼,並問我如何將它變成內聯。只能調用一次的大函數是內聯的嗎?

我告訴他這太大了,會導致指導性通貨膨脹。然後我想,但他只調用一次這個函數。所以,沒有缺點。

感覺不對。這是錯的嗎?

+3

爲什麼不看產生的裝配而不是猜測? – StoryTeller

+0

標準中沒有什麼可以說它不能。這一切都歸結於你正在使用的編譯器以及它在優化時的激進程度。 – Sean

+1

請詳細說明您正在使用的編譯器和編譯器設置。這非常適合編譯器,如果您期待的答案涵蓋所有過於寬泛的情況。 – NathanOliver

回答

9

Gcc做了這個優化。當靜態函數一旦被內聯就被調用。它不會對外部函數執行此操作,因爲它無法確定誰調用該函數。

您可以通過這裏檢查彙編:

https://gcc.godbolt.org/

首先與EXTERN功能:

#include <stdio.h> 

extern int test(int x); 

int main() { 
    int x = test(10); 

    printf("%d\n", x); 
} 

int test(int x) 
{ 
    volatile int y = x; 
    for (int i = 0; i < 10; i++) 
    y++; 
    for (int i = 0; i < 10; i++) 
    y++; 

    return y; 
} 

的主要()與-O優化,編譯器,彙編程序輸出標記:

main: 
     subq $8, %rsp 
     movl $10, %edi 
     call test(int) 
     movl %eax, %esi 
     movl $.LC0, %edi 
     movl $0, %eax 
     call printf 
     movl $0, %eax 
     addq $8, %rsp 
     ret 

您可以看到測試被調用並且EAX中的返回值存儲在$ 0中。

現在讓測試靜態並觀察測試調用消失並且代碼被內聯。

+0

不完全正確的時代,我們有鏈接時間優化。根本沒有必要考慮內聯或不內聯!也許該函數被內聯多次,但與來自調用者的其他常量。許多其他場景可能... – Klaus

0

如果您要使用此功能兩次,請不要內聯,但如果您只使用一次,則可以內聯。

+1

內聯由編譯器/優化器完成。如果統計數據表明內聯更好,他會內聯。不要考慮優化器。編譯器的這一部分比你認爲的更好! – Klaus

+3

Downvoters是驚人的。只讚揚新的答案,說完全一樣的東西。大聲笑 –

4

一個大功能可以內聯。 如果它只被調用一次,那麼沒有缺點(除了您將來可能開始調用它的可能性之外)。

編譯器是否實際優化了調用(擴展了呼叫站點的功能)是另一回事。如果函數具有內部鏈接,則很容易證明該函數只被調用一次。如果它具有外部連接,那麼只有在整個程序優化時纔有可能。