天天看點

c++知識點--extern "C" 讀書筆記

eg.

#ifdef __cplusplus

extern "C" {

#endif

#ifdef __cplusplus

}

extern "C" 包含雙重含義,從字面上即可得到:首先,被它修飾的目标是“extern”的;其次,被它修飾的目标是“C”的。讓我們來詳細解讀這兩重含義。

  被extern "C"限定的函數或變量是extern類型的;

  extern是C/C++語言中表明函數和全局變量作用範圍(可見性)的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變量可以在本子產品或其它子產品中使用。

被extern "C"修飾的變量和函數是按照C語言方式編譯和連接配接的;

 作為一種面向對象的語言,C++支援函數重載,而過程式語言C則不支援。函數被C++編譯後在符号庫中的名字與C語言的不同。例如,假設某個函數的原型為:

void foo( int x, int y );

  該函數被C編譯器編譯後在符号庫中的名字為_foo,而C++編譯器則會産生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都采用了相同的機制,生成的新名字稱為“mangled name”)。_foo_int_int這樣的名字包含了函數名、函數參數數量及類型資訊,C++就是靠這種機制來實作函數重載的。

如果這個函數在C中編譯成庫,目标檔案中函數名為_func,當這個函數中C++中被調用時,C++的編譯器就會到目标檔案中尋找_foo_int_int,結果找不到,出錯。

是以為了防止這種問題,在C++調用時,将函數聲明前加個extern "C" 告訴C++的編譯器,不要對名字再進修飾,而直接去找_func。

同樣在C++中編譯的函數,如果想讓C來使用,通常也加上extern "C"在編譯時将函數名按C的風格進行修飾。

.可以包含頭檔案,相當于頭檔案中的聲明都加了extern "C"

  extern "C"

 {

   #i nclude <cmath>

 }

   extern "C"

  {

     double sqrt(double);

     int min(int, int);

 }

接下來,我們來看下#ifdef _cplusplus/#endif _cplusplus的作用。很明顯#ifdef/#endif、#ifndef/#endif用于條件編譯,#ifdef _cplusplus/#endif _cplusplus——表示如果定義了宏_cplusplus,就執行#ifdef/#endif之間的語句,否則就不執行。

在這裡為什麼需要#ifdef _cplusplus/#endif _cplusplus呢?因為C語言中不支援extern "C"聲明,如果你明白extern "C"的作用就知道在C中也沒有必要這樣做,這就是條件編譯的作用!在.c檔案中包含了extern "C"時會出現編譯時錯誤。

C++中調用C的代碼

假設一個C的頭檔案cHeader.h中包含一個函數print(int i),為了在C++中能夠調用它,必須要加上extern關鍵字(原因在extern關鍵字那節已經介紹)。它的代碼如下:

?

1 2 3 4 5 6

#ifndef C_HEADER

#define C_HEADER

extern

void

print(

int

i);

#endif C_HEADER

相對應的實作檔案為cHeader.c的代碼為:

?

1 2 3 4 5 6

#include <stdio.h>

#include "cHeader.h"

void

print(

int

i)

{

printf

(

"cHeader %d\n"

,i);

}

現在C++的代碼檔案C++.cpp中引用C中的print(int i)函數:

?

1 2 3 4 5 6 7 8 9

extern

"C"

{

#include "cHeader.h"

}

int

main(

int

argc,

char

** argv)

{

print(3);

return

0;

}

------------------------------------

extern用在變量聲明中常常有這樣一個作用,你在*.c檔案中聲明了一個全局的變量,這個全局的變量如果要被引用,就放在*.h中并用extern來聲明。

轉載于:https://blog.51cto.com/suixinsuixin/1288544