程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 在C++中如何使用C

在C++中如何使用C

編輯:C++入門知識

在C++中如何使用C


首先,分析下面的代碼片段:

  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的方式,讓編譯器尋找_ Function而不是_ Function_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. /* C語言實現文件:CDemo.c */
  7. #include " CDemo.h"
  8. int Function ( int x, int y )
  9. {
  10. ... // processing code
  11. }
  12. // C++調用文件
  13. #include " CDemo.h"
  14. int main()
  15. {
  16. Function (2,3);
  17. return 0;
  18. }

(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. /* C語言實現文件:CDemo.c */
  7. #include "CDemo.h"
  8. int Function ( int x, int y )
  9. {
  10. ... // processing code
  11. }
  12. // C++調用文件
  13. #include "CDemo.h"
  14. extern "C" int Function(int x,int y);
  15. int main()
  16. {
  17. Function (2,3);
  18. return 0;
  19. }

(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. /* C語言實現文件:CDemo.c */
  7. #include "CDemo.h"
  8. int Function ( int x, int y )
  9. {
  10. ... // processing code
  11. }
  12. // C++調用文件
  13. extern "C" {
  14. #include "CDemo.h"
  15. }
  16. int main()
  17. {
  18. Function (2,3);
  19. return 0;
  20. }

使用中,謹記: extern "C"一定要加在C++的代碼文件中才能起作用。

請記住:

若想在C++中使用大量現成的C程序庫,實現C++與C的混合編程,那你必須了解extern "C"是怎麼回事兒,明白extern "C"的使用方式。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved