C++ における extern "C" の効果は何ですか? 質問する

C++ における extern

extern "C"C++ コードに組み込むと、具体的に何が行われますか?

例えば:

extern "C" {
   void foo();
}

ベストアンサー1

extern "C"C++ の関数名に C リンケージ (コンパイラは名前を変更しません) を持たせ、クライアントの C コードが関数の宣言のみを含む C 互換ヘッダー ファイルを使用して関数にリンク (使用) できるようにします。関数定義はバイナリ形式 (C++ コンパイラによってコンパイルされたもの) で含まれており、クライアントの C リンカーは C 名を使用してこれにリンクします。

C++ には関数名のオーバーロードがありますが、C にはオーバーロードがないため、C++ コンパイラは関数名をリンク先の一意の ID として使用することはできません。そのため、引数に関する情報を追加して名前をマングルします。C では関数名をオーバーロードできないため、C コンパイラは名前をマングルする必要はありません。C extern "C"++ で関数にリンクがあることを宣言すると、C++ コンパイラはリンクに使用される名前に引数/パラメータの型情報を追加しません。

ご参考までに、extern "C"個々の宣言/定義へのリンクを明示的に指定することも、ブロックを使用して一連の宣言/定義をグループ化し、特定のリンクを設定することもできます。

extern "C" void foo(int);
extern "C"
{
   void g(char);
   int i;
}

技術的な詳細が気になる場合は、C++03 標準のセクション 7.5 に記載されています。以下に簡単な要約を示します ( に重点を置きますextern "C")。

  • extern "C"リンケージ仕様である
  • すべてのコンパイラは「C」リンクを提供する必要がある
  • リンケージ指定は名前空間スコープ内でのみ発生するものとする
  • すべての関数型、関数名、変数名には言語リンケージがある リチャードのコメントをご覧ください:外部リンクを持つ関数名と変数名のみが言語リンクを持つ
  • 異なる言語リンクを持つ2つの関数型は、他の点では同一であっても異なる型である。
  • リンケージ仕様はネストされ、内側の仕様が最終的なリンケージを決定します
  • extern "C"クラスメンバーでは無視されます
  • 特定の名前を持つ関数は最大で 1 つだけ "C" リンケージを持つことができます (名前空間に関係なく)
  • extern "C" 関数に外部リンクを強制します(静的にすることはできません) リチャードのコメントをご覧ください: staticinsideextern "C"は有効です。このように宣言されたエンティティは内部リンケージを持ち、言語リンケージを持ちません。
  • C++から他の言語で定義されたオブジェクトへのリンク、および他の言語からC++で定義されたオブジェクトへのリンクは、実装定義であり、言語に依存します。2つの言語実装のオブジェクトレイアウト戦略が十分に類似している場合にのみ、このようなリンクを実現できます。

おすすめ記事