2012-04-06 158 views
13

在大多數情況下,如果我想創建C中的可選功能,我只需創建兩個函數是這樣的:爲什麼GCC保留空功能?

#ifdef OPTIONAL_SOMETHING 
void do_something(int n, const char *s) 
{ 
    while (n--) { 
     printf("%s", s); 
    } 

    /* ...You might get the point, really do something... */ 
} 
#else 
void do_something(int n, const char *s) 
{ 
    /* Empty body */ 
} 
#endif 

因此,如果符號未定義 - 當功能被禁用 - 一個空函數被編譯成可執行文件。

鑽研組裝上市,似乎GCC編譯並呼籲空函數時的優化是禁用。如果啓用優化,也與-O2-O3只編譯必要的堆棧處理代碼,但它優化了調用指令。總而言之,它保持了這個功能。

大約同樣適用於非空的,但未使用的方法。

它應該簡單地扔掉整個事情,但事實並非如此。爲什麼這是默認行爲?只是爲了好奇:我如何消除這種情況?

+0

「如果啓用優化,同樣使用-O2和-O3,它僅編譯必要的堆棧處理代碼,但它優化了調用指令。」這是否意味着這樣還有一些開銷? 'start_timer(); do_something(); stop_timer();'需要比'start_timer(); stop_timer();'更長的時間? – 2013-10-28 14:26:38

回答

24

由於函數具有外部鏈接(不是static),編譯器無法消除它,因爲另一個對象文件可能會引用它。如果功能是static,它將被完全消除。

+4

儘管如此,這仍然留下了爲什麼GCC沒有內聯函數體(即忽略調用)的問題。 – duskwuff 2012-04-06 22:33:44

+1

@duskwuff:我已經有編譯器內嵌的靜態函數,所以我不能在它們上設置斷點,即使我想。它可能取決於GCC或平臺的版本。否則,我不知道;我沒有參與海灣合作委員會的發展,也沒有參與有關這些問題的決定。 – 2012-04-06 22:35:27

+1

你讓我好奇,所以我只是自己試了一下:我在gcc 4.4.5和-O3(只)我沒有看到空函數被調用(無論是否靜態)。 – timday 2012-04-06 23:22:35

1

如果您希望編譯器最終內聯您要告訴他的函數。聲明你的函數inline,這允許編譯器而不是發現函數,如果它看起來合適。

現在這可能會導致一個「未定義的符號」錯誤,當你編譯-O0左右。把一個 「實例」 像

void do_something(int n, const char *s); 

在短短的一個編譯單元(.c文件)。