[解決済み] C++とCの融合 - #ifdef __cplusplus はどのように機能するのか?
質問
レガシーが多いプロジェクトに携わっています。
C
のコードです。 私たちはC++で書き始めましたが、最終的にはレガシーコードも変換するつもりです。 がどのように変換されるのか、少し混乱しています。
C
とC++の相互作用について教えてください。 をラップすることで
C
のコードを
extern "C"
C++ コンパイラは
C
のコードの名前をどう実装すればいいのか、全く分からない。
そこで、それぞれの C ヘッダーファイル(インクルードガードの後)には
#ifdef __cplusplus
extern "C" {
#endif
と書き、一番下には
#ifdef __cplusplus
}
#endif
この2つの間に、include、typedef、関数のプロトタイプをすべて配置します。 私がこのことを正しく理解しているかどうか、いくつか質問があります。
-
C++のファイルA.hhがあるとして、それが を含んでいます。 C ヘッダーファイル B.h, は別の C ヘッダーファイル C.h, はどのように動作するのでしょうか? 私が思うに コンパイラがB.hに踏み込むと
__cplusplus
が定義されているので で囲みます。extern "C"
(そして__cplusplus
にはなりません。 このブロックの内部で定義されます)。 だから に踏み込むと、C.h,__cplusplus
は定義されません。 でラップされることはありません。extern "C"
. これは正しいのでしょうか? -
を使用することに何か問題があるのでしょうか? でラップする。
extern "C" { extern "C" { .. } }
? 2つ目のextern "C"
はどうする? -
このラッパーは.cファイルには付けず、.hファイルだけに付けます。 では、関数にプロトタイプがない場合はどうなるのでしょうか?コンパイラはそれをC++の関数だと思うのでしょうか?
-
また、サードパーティの で書かれたコードです。 C であり このようなラッパーはありません。 となります。 ヘッダをインクルードするときは常に そのライブラリから は
extern "C"
を#includeで囲んでいます。 これは正しい対処法でしょうか? ということでしょうか? -
最後に、この設定で良いのでしょうか? 他にやるべきことはありますか? これからミキシングするのは C とC++の この先もずっとそうであるように、私は をカバーできるようにしたい。 ということです。
解決方法は?
extern "C"
は、コンパイラがコードを読み取る方法を変えるものではありません。 コードが .c ファイルにあれば C としてコンパイルされ、.cpp ファイルにあれば C++ としてコンパイルされます (設定に何か変なことをしない限り)。
何
extern "C"
は、リンクに影響を与えます。 C++の関数は、コンパイルされるときに、その名前が変形されます。 関数名はパラメータの型と数に基づいて変更されるため、同じ名前の2つの関数は異なるシンボル名を持つことになります。
の中のコードは
extern "C"
はC++のコードのままです。 extern "C"ブロックの中でできることには制限がありますが、それはすべてリンクに関するものです。 Cのリンクで構築できない新しいシンボルを定義することはできません。 つまり、例えばクラスやテンプレートはダメということです。
extern "C"
ブロックがうまくネストしています。 また
extern "C++"
の中に閉じ込められ、どうしようもなくなってしまった場合。
extern "C"
リージョンは、クリーンルームの観点からはあまり良いアイデアではありません。
では、具体的に番号のついた質問について。
1について: __cplusplusは、以下の内部で定義されたままです。
extern "C"
ブロックを使用します。 しかし、ブロックはきちんとネストされるべきなので、これは重要ではありません。
2について: __cplusplusは、C++コンパイラを通して実行されているすべてのコンパイル単位で定義されます。 一般的に、それは.cppファイルと、その.cppファイルによってインクルードされるすべてのファイルを意味します。 同じ .h (または .hh や .hpp など) が、異なるコンパイル単位に含まれる場合、異なる時点で C または C++ として解釈される可能性があります。 もし、.hファイルのプロトタイプがCのシンボル名を参照するようにしたい場合は、プロトタイプに
extern "C"
は、C++として解釈されるときには
extern "C"
として解釈されます。
#ifdef __cplusplus
をチェックします。
質問の答えその3:プロトタイプを持たない関数は、.cppファイル内で
extern "C"
ブロックがあります。 なぜなら、プロトタイプを持たない関数は、同じファイル内の他の関数からしか呼び出されないからです。
4については、まさにその通りです。 もしあなたがCリンケージを持つコード(例えばCコンパイラでコンパイルされたコード)のヘッダをインクルードしているなら、次のようにしなければなりません。
extern "C"
そうすれば、そのライブラリとリンクすることができます。 (そうすれば、ライブラリとリンクすることができます(そうしないと、リンカは
_Z1hic
を探しているときに
void h(int, char)
5: このような混在は、一般的な理由で
extern "C"
そして、この方法で行うことは何も悪いことだとは思いません。
関連
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] C言語とC++の両方で有効なコードを、それぞれの言語でコンパイルすると、異なる動作になることがありますか?
-
[解決済み] C++テンプレート関数定義の.CPPファイルへの格納
-
[解決済み】画像処理。コカ・コーラ缶」認識のためのアルゴリズム改良
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み】C言語の関数ポインタはどのように機能するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み] 既に.objで定義されている-二重包含はない
-
[解決済み】C++の余分な資格エラー
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された