14

だから、James Kanze と Loki Astari から C リンケージについて教えられている間、私はこれについて疑問に思っていました:

extern "C" int foo1 (void (*)());
extern "C" { int foo2 (void (*)()); }

foo1学校教育の後、C リンケージでは関数ポインターのみを使用するのに対し、C++ リンケージでは関数ポインターのみを使用する必要があると思いますfoo2。私の理解は正しいですか?上記の例の違いを説明する C++ 標準の特定のリファレンスはありますか?

編集:誰もが簡単にフォローできるように、C++ 11 ドラフト標準の関連部分を含むペーストビンをここに示します

4

3 に答える 3

9

[dcl.link] 7.5p4 に示すように、foo1 は C 関数へのポインターを受け取ります。

リンケージ仕様では、指定された言語リンケージは、すべての関数宣言子の関数型、外部リンケージを持つ関数名、およびリンケージ仕様内で宣言された外部リンケージを持つ変数名に適用されます。[例:

extern "C" void f1(void(*pf)(int));
                                                                 // f1 という名前とその関数型には C 言語の
                                                                 // リンケージがあります。pf は C 関数へのポインタです

この例は直接適用されfoo1、追加された強調は、私がその理由であると考えるものを強調しています. 関数のパラメーター リストにはパラメーターの関数宣言子が含まれており、すべての関数宣言子はリンケージ仕様の影響を受けます。これは、ブレース付きおよびブレースなしのリンケージ仕様の両方に適用されます。

中括弧を使用しない場合のいくつかの違いは、名前が自動的externに指定され、ストレージ指定子の明示的な使用が禁止されていることです。

extern "C" int i; // not a definition

int main() {
    i = 1; // error, no definition
}

extern "C" static void g(); // error

この違いが問題となる例として、以下を含むヘッダーを考えてみましょう。

extern "C" int a;
extern "C" double b;
extern "C" char c;

誰かがこれを次のように変更したくなるかもしれません:

extern "C" {
    int a;
    double b;
    char c;
}

しかし、それは宣言を定義に変換するため、正しくありません。代わりに、使用する正しいコードextern "C" {}は次のとおりです。

extern "C" {
    extern int a;
    extern double b;
    extern char c;
}
于 2012-08-08T22:48:41.400 に答える