extern “C” 作用

  1. #ifdef  __cplusplus  
  2. extern "C" {  
  3. #endif  
  4. …… (C函數聲明)  
  5. #ifdef  __cplusplus  
  6. }  
  7. #endif  

        簡單來說,這個extern“C”用於C++代碼調用C的函數(至於C代碼如何調用C++函數,還是問問Google大神吧~)

        先撇開上述的extern “C”,看看C函數和C++函數的彙編代碼,就知道在目標文件中,C函數名和C++函數名採用不同的命名規則。

        VS2010新建一個Windows Console工程,添加一個.c和.cpp文件,文件裏的代碼都一樣,如下

  1. void hello()  
  2. {  
  3.   
  4. }  

        爲了使彙編文件的內容簡單一些,這裏函數體是空,而且沒有引入任何頭文件。VS2010默認不輸出.asm文件,即彙編文件。在工程的配置中,讓VS2010輸出彙編文件,如下


        編譯解決方案(或按“F7”),可以在工程目錄的Debug文件夾下,找到對應的兩個彙編文件,內容如下


        沒有必要把這裏全部的彙編代碼看懂,只要明白在源代碼中同一個hello函數,在翻譯過來的.asm文件中,hello函數名的命名不一樣就行了。

        很明顯,如果C++代碼要調用C函數,需要按照C函數編譯後的函數名去調用這個函數。所以,extern “C”的作用就是告訴編譯器,花括號“{}”中間的這些函數聲明全部都是C函數。

        下面修改一下.c和.cpp文件的內容,如下

  1. // C代碼  
  2. #include <stdio.h>  
  3.   
  4. void hello()  
  5. {  
  6.     printf("Hello, world!\n");  
  7. }  
  1. // C++代碼  
  2. void hello();  
  3.   
  4. int main(void)  
  5. {  
  6.     hello();  
  7. }  

        這裏要說明下,由於.c和.cpp文件在同一個工程下,所以簡單起見,沒有使用頭文件引入hello函數,這裏hello函數是全局的。運行工程發現出錯如下


        這裏?hello@@YAXXZ就是上面.cpp文件中hello函數編譯後出現在對應的.asm文件中的。顯然,編譯器按照這個名稱去找目標文件(.obj文件)中的hello是找不到的,因爲.c文件編譯後的.obj文件中,hello函數名被改成_hello。

        這時,把extern “C”加到.cpp文件中,如下

  1. extern "C" {  
  2.     void hello();  
  3. };  
  4.   
  5. int main(void)  
  6. {  
  7.     hello();  
  8. }  

        果然,程序可以通過編譯運行了。到這裏,基本上extern ”C”的作用都講清楚了。至於__cplusplus宏,用於判斷當前源文件是不是C++源文件,因爲extern “C”這種寫法在C源文件中不允許的,如下,所以使用__cplusplus宏可以避免extern “C”被引入到C源文件中。即

(1)當前源文件是C++,則__cplusplus宏生效,extern “C”以及花括號“{}”的內容被引入C++源代碼中;

(2)當前源文件是C,則__cplusplus宏無效,extern “C”以及花括號“{}”的內容不被引入C源代碼中。

conclusion:

extern "c"就是告訴C++編譯器這是一個C程序,請按C命名方式編譯,否則有些函數調用出錯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章