46

*.hライブラリのヘッダーファイルで、関数Cを宣言する必要があります

extern void f();

// or only 

void f();
  1. でのみ使用する場合C
  2. から使用する場合C++
4

5 に答える 5

55

externCまたはC++のいずれかで関数を宣言するときに、キーワードを使用する必要は[ほとんど]ありません。CおよびC++では、すべての関数にデフォルトで外部リンケージがあります。ヘッダーファイルで関数を宣言するという奇妙な習慣には、externおそらくいくつかの歴史的なルーツがありますが、それはすでに何十年もの間完全に無関係です。

上記のCには、上記の1つの[あいまいな?]例外があります。これは、おそらくあなたが質問していることに直接関係していません。C言語(C99)で、ある翻訳単位で関数が次のように定義され、次のようinline に宣言されている場合extern(明示的externな使用)その場合、その関数のインライン定義は外部定義としても機能します。明示的な宣言がextern変換ユニットに存在しない場合、インライン定義は「内部」定義としてのみ使用されます。

PS C ++のようなものがありますextern "C"が、それはまったく別の問題です。

于 2012-07-29T20:48:38.230 に答える
25

Cライブラリのヘッダーファイルで、関数を宣言する必要があります。

extern void f();
// or only
void f();

問題1:セマンティクス

C ++プログラムでは、関数は値を返さず、引数をとらない関数として宣言されます。

Cプログラムでは、関数は値を返さず、不定であるが可変長の引数のリストをとらない関数として宣言されます。

Cで「引数なし」の意味を取得するには、次のいずれかを使用します。

extern void f(void);
void f(void);

同じ表記法は、C ++でも同じことを意味しますが、純粋なC ++コードの場合void、引数リストでの使用は慣用的ではありません(純粋なC ++コードでは使用しないでください)。

問題2:CとC++間の相互作用

トリッキーですが、通常のルールでは、関数をC++コードに対して。として宣言する必要がありますextern "C"__cplusplus両方に同じソースコードを使用するには、マクロをテストする必要があります。通常、次のようなことを行います。

#ifdef __cplusplus
#define EXTERN_C       extern "C"
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END   }
#else
#define EXTERN_C       /* Nothing */
#define EXTERN_C_BEGIN /* Nothing */
#define EXTERN_C_END   /* Nothing */
#endif

EXTERN_C void f(void);

EXTERN_C_BEGIN
    void f(void);
    int  g(int);
EXTERN_C_END

オプションとバリエーションは多岐にわたりますが、ヘッダーはCとC++の両方で使用できます。

マクロは通常、あらゆる場所で使用される1つの汎用ヘッダーで定義されます。次に、特定のヘッダーによって、汎用ヘッダーが確実に含まれ、適切な形式のマクロが使用されます。

問題3:スタイル

extern正式には、関数宣言の前に表記する必要はありません。ただし、これは外部で定義された関数の宣言であることを強調するために、またヘッダーでグローバル変数が宣言されている場合の(まれな)場合との対称性のために、ヘッダーで使用します。

人々はこれについて意見を異にすることができますし、そうします。私はローカルルールを使用しますが、ルール作成者の場合、externはヘッダーに含まれています。

于 2012-07-29T20:49:44.550 に答える
5

一般的な使用のために次のように宣言します

#ifdef __cplusplus
extern "C" {
#endif
  void f(void);
#ifdef __cplusplus
}
#endif

それ以外の場合externは、廃止されます。

于 2012-07-29T20:40:35.607 に答える
1

後者は完全に問題ありません。これは、このヘッダーを含む関数の定義にすぎないためです。「このプロトタイプの関数がこのあたりにあります」

この文脈では、関数は変数とは明らかに異なりますが、それは別の問題です。ただし、関数本体を「インライン」またはクラス定義の一部(C ++)または「テンプレート関数」(C ++)として宣言しない限り、関数本体を含めないようにしてください。

于 2012-07-29T20:41:35.523 に答える
1

関数プロトタイプでexternを指定しても、デフォルトで想定されているため、効果はありません。コンパイラがプロトタイプを見るときはいつでも、関数がどこか別の場所(現在または別の変換ユニット内)で定義されていると想定します。これは両方の言語に当てはまります。

次のスレッドには、externに関する一般的な有用なコメントがいくつかあります。

C関数に対するexternキーワードの影響

于 2012-07-29T20:49:03.377 に答える