2011-08-22 49 views
2

C編程語言有沒有一種方法可以檢查頭文件中的函數原型是否與編譯時的實際函數定義相對應。 例如,如果我創建了頭文件,然後更改該頭文件中描述的某個函數的簽名,我可以在編譯時檢查頭文件中是否有錯誤的原型?在編譯之前,這是編譯器或其他工具的工作嗎? 謝謝。如何檢查C編程語言中頭文件的有效性

+0

您的函數是在您編譯的其他資源中還是在庫中?如果您在這裏自己編譯它們,那麼當您使用不同的簽名編譯函數定義時,您應該會遇到錯誤。 – Rup

+0

如果函數在某個庫中,並且已經編譯了源代碼。所以,我有錯誤的函數簽名頭文件和已編譯該函數的源文件。當我編譯包含該頭文件的其他源文件時,編譯器會抱怨嗎? – vldmrrdjcc

+1

在編譯時:否 - 編譯器會相信頭文件對於新代碼是正確的。根據您的系統,某些情況下鏈接時可能會出現錯誤,例如在Windows上,如果您使用__stdcall調用約定,則參數的字節數將包含在生成的符號中(例如_strcpy @ 8),因此如果簽名中的參數數量已更改,則會出現鏈接器錯誤。 – Rup

回答

1

這是編譯器我的經驗,並在它是相當不錯:)

如果你的函數原型在頭文件不匹配它的源文件中定義的工作,那麼你就無法使用該功能其他源文件,因爲它沒有被聲明,並且編譯器會通過提供錯誤來通知你。

+0

如果在編譯時包含一些頭文件的源文件在編譯時不可用,那麼編譯器應該抱怨嗎? – vldmrrdjcc

+0

@Vladimir Radojicic:如果一個源文件包含一個不存在的頭文件,那麼編譯器會給出錯誤,說明找不到該頭文件。 –

+0

我的意思是在頭文件中執行某些函數的源代碼不存在,而不是頭文件本身。 – vldmrrdjcc

2

如果你有兩個不同的原型聲明相同的函數名,編譯器應該抓住這一點,即:

int foo(int a, int b); 

... 

int foo(int a, float b) { ... } 

當然,如果你真的重命名功能,那麼編譯器能不能抓住它,即:

int foo(int a, int b); 

... 

int fee(int a, int b) { ... } 

除非你試圖從其他地方撥打foo。然後鏈接器會投訴。

+0

如果我有原型int foo(int a,int b);並且該函數的實現是int foo(int a,float b){...},例如錯誤。當我編譯一些包含這個頭文件的源代碼時,如果在那一刻編譯器只有源代碼包含頭文件和頭文件,而沒有頭文件函數的源代碼實現,那麼它可以捕獲錯誤嗎? – vldmrrdjcc

+1

@Vladimir:編譯器應該給你一個錯誤,說明當你用'foo'的實現編譯源文件時,「foo'的衝突類型(或類似的東西)」。它不會給你任何其他源文件的警告。但是如果你改變了頭文件,你的編譯系統也應該嘗試重新編譯實現源文件! –

+0

因此,當我編譯其他不包含foo實現的源文件時,它只是包含具有foo錯誤簽名的頭文件,編譯器不會給出任何警告。但它有自動機制來檢查頭文件和實現文件中的函數原型差異? – vldmrrdjcc

0

如果使用該函數,編譯器會給你一個鏈接器錯誤,如果原型的實現不存在。但是,如果你從不使用該函數(例如,當你建立一個庫),鏈接器不會抱怨。

這是你應該確保在你的測試中有很好的代碼覆蓋率的原因之一 - 如果你有例如一些單元測試也被編譯,連接器會發出抱怨。如果你有一些你不能測試的函數,並且不會從你的代碼中調用,你可以編寫一個虛擬的可執行文件(不需要工作)來調用所有這些函數。

最後的解決方案是使用clang庫編寫自己的代碼檢查程序。