我正在撰寫一個 C 庫,它可能對撰寫 C 的人有用。它有一個標題,如下所示:
#ifndef FOO_H_
#define FOO_H_
#include <bar.h>
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void foo_func();
#ifdef __cplusplus
}
#endif
#endif
我想知道 - 我應該extern "C"在包含標頭包含指令之前移動位嗎?特別是看到在實踐中,其中一些標題本身可能有一個extern "C"?
uj5u.com熱心網友回復:
不,通常您不應該移動它以包含標題。
extern "C"用于指示函式正在使用 C 呼叫約定。該宣告對變數、#defines 或其他包含沒有影響(除非您在 C 檔案中包含沒有 C 支持的 C 庫)。
如果沒有宣告,當使用 C 編譯器編譯時,假定函式遵循 C 約定,當使用 C 編譯器編譯時,假定函式遵循 C 約定。如果 C 和 C 代碼使用相同的頭檔案,則會出現聯結器錯誤,因為編譯后的函式在 C 和 C 中具有不同的名稱。
盡管可以將所有代碼放在 #ifdef 塊之間,但我個人不喜歡它,因為它實際上僅用于函式原型,而且我經常看到人們將其復制粘貼到不應該出現的位置。最簡潔的方法是將它保留在它應該在的位置,即圍繞 C/C 頭檔案中的函式原型。
因此,要回答您的問題“我應該extern "C"在包含標頭包含指令之前移動該位嗎?”,我的回答是:不,您不應該。
但有可能嗎?是的,它可能不會破壞任何東西,但不是必需的。
當您真正需要它時,有一個例外:當 C 庫不包含這些構造并且您想在 C 專案中使用該庫時,您可以使用extern "C".
uj5u.com熱心網友回復:
令人驚訝的是。現在閱讀標準后,我什至會寫
#ifndef FOO_H_
#define FOO_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <bar.h>
#include <stdarg.h>
#include <stddef.h>
void foo_func();
#ifdef __cplusplus
}
#endif
#endif
有兩個原因:
1 嵌套extern "C"沒問題,所以你的bar.h包含就可以了。這樣看起來更清晰更重要
2 要真正可移植,您必須extern "C"為 C 用戶封裝C 頭檔案,如果他們不想的話。
因為我只是查看了 C 標準和 16.5.2.3 Linkage [using.linkage] 狀態
使用外部鏈接宣告的 C 標準庫中的名稱是否具有 extern "C" 或 extern "C " 鏈接是實作定義的。為此,建議實作使用 extern "C " 鏈接。 1
為了安全起見,您確實應該將extern "C"這些包含包裹起來,但是,您不應該這樣做,因為這意味著 D.9 C 標頭 [depr.c.headers] 中的標頭與<stdlib.h>您正在使用的一樣。
uj5u.com熱心網友回復:
這在C FAQ 中有介紹。
首先,如何在 C 代碼中包含標準的C 頭檔案?不需要什么特別的,因為標準 C 頭檔案可以與 C 無縫協作。所以,你不需要包裝stdarg.h和stddef.h在extern "C"。
那么,對于非標準的 C 頭檔案,有兩種可能:要么你不能改變頭檔案,要么你可以改變頭檔案。
當你不能改變的C頭,包裹#include在extern "C"。
// This is C code
extern "C" {
// Get declaration for f(int i, char c, float x)
#include "my-C-code.h"
}
int main()
{
f(7, 'x', 3.14); // Note: nothing unusual in the call
// ...
}
當您可以更改 header 時,編輯它以有條件地包含extern "C"在 header 本身中:
#ifdef __cplusplus
extern "C" {
#endif
. . .
#ifdef __cplusplus
}
#endif
在您的情況下,這歸結為您是否可以控制bar.h. 如果它是您的標題,那么您應該修改它以包含extern "C"而不是包裝它#include本身。
無論如何/何時/何地包含標題,標題都應該以相同的方式作業。包裝#includein extern "C"、#pragma pack、 special #defines 等應保留用于最后的解決方法,因為這可能會干擾標頭在不同場景中的行為,從長遠來看會降低系統的可維護性。
正如 StoryTeller 在評論中所說:
一些頭檔案是在最外層“范圍”具有 C 語言鏈接的假設下明確撰寫的。它們可能用于
__cplusplus洗掉模板宣告,如果您按照自己的意愿將它們包裝起來,您的標題將從根本上被破壞。所以如前所述,使您的宣告正確,并讓其他標題不受阻礙地做他們的事情。甚至標準庫頭檔案也可能會損壞(因為實作者可能會推斷它無論如何都會被共享,然后在里面做一些專家友好的事情)。
請注意,標準 C 頭檔案可以使用 C 鏈接實作,但也可以使用 C 鏈接實作。在這種情況下,將它們包裝起來extern "C"可能會導致鏈接錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/327467.html
