2010-05-16 48 views
25

我有許多C源文件(包括.c和.h文件)。頭文件包含許多函數。在這些函數中,只有部分用在源文件中。假設a.h,b.h是頭文件,a.c和b.c是.c文件。 a.h包含在a.c中。但是隻有一些功能在那裏。 h被使用,其餘不被使用。編譯後,我發現以下警告:功能已定義但未在C中使用警告

function XXXX defined but not used. 

但是那些在a.c中沒有使用的XXXX函數在b.c中使用。所以,我也不能完全刪除這些功能。因此,我決定製作一個單獨的文件,其中只包含那些XXXX函數,並將其包含在任何使用它的地方。這樣做是爲了創建多個頭文件。任何人都可以請我建議一些有效的方法來解決這個問題。

+0

這對我來說不是問題。關於你的函數聲明或編譯的方式肯定有些奇怪。你能提供更多細節嗎? – crazyscot 2010-05-16 22:34:45

+2

我想我們需要看到一些代碼,因爲這不會正常發生 - 請參閱標準頭文件示例 – Mark 2010-05-16 22:35:52

+0

您正在使用哪種編譯器? – berkay 2010-05-16 22:39:19

回答

57

「功能已定義但未使用」警告僅針對內部連接的功能發出,即聲明爲static的功能。這些功能只能在一個翻譯單元中訪問,因此編譯器總是知道它們是否被使用(在程序中)。如果您未在其翻譯單元中引用這些功能,則已知這些功能未被使用,並且會生成警告。

您在說這些函數「不在a.c中使用,但在b.c中使用」。這不是真的。當您在頭文件中聲明(並定義)一個函數爲static時,包含該頭文件的每個翻譯單元都會獲得其自己的該函數的內部副本。即使這些功能看起來完全相同,它們仍然是獨立的,完全獨立的功能。它們具有相同的名稱並且由相同的代碼組成的事實對編譯器沒有任何意義。因此,在b.c中,您獲得了完全獨立的函數副本(如您所說),但a.c中的完全獨立副本仍未使用。

在這種情況下的問題是爲什麼你這樣做。爲什麼在地球上你在頭文件中定義了靜態函數?如果你真的需要這樣做(即如果你真的想在每個翻譯單元中產生一個單獨的內部「克隆」這個函數),你可以通過使用一些特定的編譯器手段來解決警告。例如,像在GCC中一樣,您可以使用__attribute__((unused))聲明函數,此函數的警告將不再發出。

但通常不需要在頭文件中定義函數。通常使用外部鏈接(即沒有0​​)的函數,將其定義在.c文件之一中,並將聲明(原型)放入頭文件中。在這種情況下,編譯器不會發出任何警告,即使該函數已聲明但未在某些翻譯單元中使用。

+0

當一個函數翻譯爲另一個函數以賦予其更多的含義時,創建函數庫非常有用,例如'static bool CanHazCheezBurger(){return flags&(HAZCHEEZ | HAZBURGER)}'。它嘗試內聯,但它失敗,因爲沒有內聯,只能複製。 – Leonardo 2014-06-14 23:06:10

6

如果你只想隱藏警告,使用方法:

-Wno-unused-function 

但是,你應該遵循的建議在caf's answer代替。這聽起來像你可能已經定義了一個函數,當你只是想添加它的聲明。

+1

從我的閱讀中,我猜想這些警告是非常有效的,不應該被隱藏。我認爲Andrey和caf是正確的,因爲OP在.h文件中定義了靜態函數。簡單地隱藏這些警告將不會有幫助;很可能會導致更大的問題。 – 2010-05-17 01:23:59

+0

你說得對,我認爲上面的caf的答案可能是正確的。 HTTP://計算器。com/questions/2845748/function-defined-but-not-used-warning-in-c/2846030#2846030我現在編輯了我的。 – thomasrutter 2010-05-17 05:18:27

5

這聽起來像你的問題是你定義函數.h文件。不要這樣做。相反,只要把你的聲明.h文件,並有配套.c文件,其中包含了函數定義:

COMMON.H:

#ifndef _COMMON_H 
#define _COMMON_H 

int foo(int a, int b); 

int bar(double x, double y, double z); 

#endif /* _COMMON_H */ 

common.c中:

#include "common.h" 

int foo(int a, int b) 
{ 
    /* code */ 
} 

int bar(double x, double y, double z) 
{ 
    /* code */ 
} 

然後你的a.cb.c sh #include "common.h",你需要安排將common.c編譯到完整的程序中。

4

另一種可能性是將這些函數定義爲inline而不是static。在這種情況下,它們需要在頭文件中定義,以便在調用它們的任何地方都可以看到定義。

編譯器會在每個使用函數的地方內聯代碼,所以要小心這是你真正想要的。 Here's an answer,並對這些折衷進行了很好的討論。

+0

我認爲inline關鍵字只是編譯器的一個建議? – Michael 2017-04-13 08:20:16

6

作爲「不這樣做」的替代方案,請考慮以下內容 - 一組將觸發最多三個未使用的函數警告的函數。

static int get_version_number(void) { return 42; } 
static double hidden_global_variable(void) { return 3.14; } 
static int potential_alternative_to_macro(int x) { return 4 * x; } 

寫另一個功能,可能是基於頭文件的名稱,

static void wno_unused_myheadername(void) 
{ 
    /* don't need to actually call the functions to avoid the warnings */ 
    (void)&get_version_number; 
    (void)&hidden_global_variable; 
    (void)&potential_alternative_to_macro; 
    return; 
} 

我們現在下降到一個未使用的功能警告。如果在包含頭文件的文件中聲明的任何外部函數中添加對wno_unused_myheadername()的調用,則整個未使用的函數警告集將消失。因爲他們現在都被使用了。

編譯器將從任何地方去除任何未使用的函數,包括wno_unused_myheadername,因爲它可以看到所有的定義,並且可能確定對wno_unused函數的單個調用實際上並沒有執行任何操作。

我已經檢查了上述消除了在叮噹聲和gcc下的預期警告,您的milage可能會因其他編譯器而異。我沒有看過asm輸出來調查幾乎未使用的函數何時被剝離。

至於爲什麼 - 一個很好的理由會使用很多小函數,這些函數非常適合在C89中內聯,它沒有inline關鍵字,而且不需要編譯器的鏈接時間優化。

相關問題