C++でのCの使い方

46918 ワード

まず、次のコードフラグメントを分析します.

  
  
  
  
  1. // Demo.h  
  2. #ifndef SRC_DEMO_H  
  3. #define SRC_DEMO_H  
  4. extern "C"  
  5. {  
  6. ...  // do something  
  7. }  
  8. #endif  // SRC_DEMO_H 

ヘッダファイルにおけるコンパイルマクロ「#ifndef SRC_DEMO_H、#define SRC_DEMO_H、#endif」の役割は、ヘッダファイルの重複参照を防止することであることは明らかである.では、extern「C」にはどんな特殊な役割があるのでしょうか.とりあえずこの疑問を残しておきます.
C++言語は「C with classes」「a better C」または「Cの超集合」と呼ばれているが、C言語に対応するすべてのものではなく、両者の間の「大同」はその中の「小異」を完全に抹殺することはできない.最も一般的な違いは、Cがvoidタイプのポインタから他のタイプのポインタに暗黙的に変換することを許可することであるが、C++は安全を考慮するためにこのような行為を禁止することを明示している.たとえば、次のコードはC言語で有効です.

  
  
  
  
  1. //  void*  double*  
  2. double *pDouble = malloc(nCount * sizeof(double)); 

ただし、C++で正しく動作するには、次のように明示的に変換する必要があります.

  
  
  
  
  1. double *pDouble = (double *)malloc(nCount * sizeof(double)); 

このほか、newやclassはC++でキーワードであり、Cでは変数名として使用できるなど、移植可能な問題もあります.
C++で既存のCライブラリを大量に使用するには、extern"C"{/*code*/}に入れる必要があります.ここまで来ると、本提案がリストし始めたコードクリップのマクロの実際の役割が分かるかもしれません.もちろん、好奇心の強い読者には、なぜextern「C」{/*code*/}を加えると使いやすいのかという新しい質問があるかもしれません.これは問題です.次に、この現象の背後に隠されている本当の原因を分析します.CとC++は異なるコンパイルとリンク方式を持っています.Cコンパイラは関数をコンパイルする時、関数のタイプ情報を持たず、関数記号の名前だけを含む.一方,C++コンパイラは関数のリロードを実現するために,コンパイル時に関数のタイプ情報を持ち込む.関数のプロトタイプを次のように仮定します.

  
  
  
  
  1. int Function(int a, float b); 

Cコンパイラはこの関数を類似にコンパイルするFunctionのシンボル(このシンボルは一般的にmangled nameと呼ばれています)は、Cリンクがこのシンボルを見つけさえすれば、接続に成功し、呼び出しを実現することができます.Cコンパイラはそのパラメータタイプ情報を検証しないが,これらの情報が正しいと仮定するのがCコンパイラの欠点である.一方、セキュリティを強調するC++では、コンパイラがパラメータタイプ情報をチェックし、上記の関数のプロトタイプが_にコンパイルされます.Function_int_floatのような記号(このメカニズムこそ関数リロードの実現に必要なサポートを提供する).リンクは、接続中に関数プロトタイプが存在するモジュールによって生成されたターゲットファイルで検索されます.Function_int_floatのような記号.
上記の矛盾を解決することはextern「C」という文法を設定する最も直接的な原因と動力となっている.extern"C"の役割はC++リンクに呼び出し関数の記号を探すように教える場合、Cの方式を採用して、コンパイラに_を探させることです.ではなくFunctionFunction_int_float.
C++でCを呼び出すコードを実装するには、以下の方法があります.
(1)Cコードのヘッダファイルを修正し,C++コードが含まれている場合は宣言にextern"C"を加える.コードは次のとおりです.

  
  
  
  
  1. /*C :CDemo.h */  
  2. #ifndef C_SRC_DEMO_H  
  3. #define C_SRC_DEMO_H  
  4. extern "C" int Function(int x,int y);  
  5. #endif  // C_SRC_DEMO_H  
  6.  
  7. /* C :CDemo.c */  
  8. #include " CDemo.h"  
  9. int Function ( int x, int y )  
  10. {  
  11.   ... // processing code  
  12. }  
  13.  
  14. // C++  
  15. #include " CDemo.h"  
  16. int main()  
  17. {  
  18.      Function (2,3);  
  19.      return 0;  

(2)C++コードでC関数を再宣言し,再宣言時にextern"C"を追加する.コードは次のとおりです.

  
  
  
  
  1. /*C :CDemo.h */  
  2. #ifndef C_SRC_DEMO_H  
  3. #define C_SRC_DEMO_H  
  4. extern int Function(int x,int y);  
  5. #endif  // C_SRC_DEMO_H  
  6.  
  7. /* C :CDemo.c */  
  8. #include "CDemo.h"  
  9. int Function ( int x, int y )  
  10. {  
  11.   ... // processing code  
  12. }  
  13.  
  14. // C++  
  15. #include "CDemo.h"  
  16. extern "C" int Function(int x,int y);  
  17.  
  18. int main()  
  19. {  
  20.      Function (2,3);  
  21.      return 0;  

(3)Cヘッダファイルを含む場合はextern"C"を添付する.コードは次のとおりです.

  
  
  
  
  1. /*C :CDemo.h */  
  2. #ifndef C_SRC_DEMO_H  
  3. #define C_SRC_DEMO_H  
  4. extern int Function(int x,int y);  
  5. #endif  // C_SRC_DEMO_H  
  6.  
  7. /* C :CDemo.c */  
  8. #include "CDemo.h"  
  9. int Function ( int x, int y )  
  10. {  
  11.   ... // processing code  
  12. }  
  13.  
  14. // C++  
  15. extern "C" {  
  16. #include "CDemo.h"  
  17. }  
  18.  
  19. int main()  
  20. {  
  21.      Function (2,3);  
  22.      return 0;  

使用中、extern「C」は必ずC++のコードファイルに追加してこそ機能することを覚えておいてください.
覚えておいてください:
C++で既存のCライブラリを大量に使用し、C++とCのハイブリッドプログラミングを実現するには、extern「C」がどういうことなのか、extern「C」の使い方を理解しなければなりません.