作用:實現C和C++混合編程。
原理:C和C++編譯器編譯之後,函數名會編譯成不同的名字,鏈接階段名字查找會找不到目標,後面實例中會詳解。
用法:①.c文件中定義的函數,.cpp文件要調用時,該.cpp文件中要用extern "C"聲明該函數;②反過來,.cpp文件中定義的函數,.c文件要調用,則同樣要在.cpp文件中用extern "C"聲明,.c文件只用普通的extern聲明。
兩個源文件分別編譯成.o文件,再鏈接成執行文件。鏈接.o文件生成執行文件時,必須得用g++。
實例:
在源文件中聲明的,沒有頭文件
.c文件定義的函數,.cpp文件調用:
1 //.c文件定義的函數 2 extern int myadd(int a, int b); 3 4 int myadd(int a, int b) 5 { 6 return a+b; 7 }
1 //.cpp文件調用 2 #include <iostream> 3 using namespace std; 4 5 extern "C" int myadd(int a, int b); 6 7 int main() 8 { 9 cout << myadd(3, 7) << endl; 10 return 0; 11 }
.cpp文件定義的函數,.c文件調用:
1 //.cpp文件定義的函數 2 extern "C" int myadd(int a, int b); 3 4 int myadd(int a, int b) 5 { 6 return a + b; 7 }
1 //.c文件調用 2 #include <stdio.h> 3 4 extern int myadd(int a, int b); 5 6 int main() 7 { 8 printf("%d\n", myadd(3, 7)); 9 return 0; 10 }
如果在頭文件中聲明,則.c文件正常的包含該頭文件,.cpp文件應該用
1 //.cpp文件的包含方式 2 extern "C" 3 { 4 #include "myHead.h" 5 }
的方式來包含頭文件,該頭文件中聲明的函數都為C方式編譯。
原理補充:C文件中,上述函數編譯之後的函數名為類似於_myadd的形式,而CPP的編譯之後函數名為類似於_myadd_int_int的形式,因為CPP要支持重載,用這種方式來區別重載的函數。
extern "C" 包含雙重含義,從字面上即可得到:首先,被它修飾的目標是“extern”的;其次,被它修飾的目標是“C”的。讓我們來詳細解讀這兩重含義。
(1) 被extern "C"限定的函數或變量是extern類型的
extern是C/C++語言中表明函數和全局變量作用范圍(可見性)的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變量可以在本模塊或其它模塊中使用。記住,下列語句:
extern int a;
僅僅是一個變量的聲明,其並不是在定義變量a,並未為a分配內存空間。變量a在所有模塊中作為一種全局變量只能被定義一次,否則會出現連接錯誤。
通常,在模塊的頭文件中對本模塊提供給其它模塊引用的函數和全局變量以關鍵字extern聲明。例如,如果模塊B欲引用該模塊A中定義的全局變量和函數時只需包含模塊A的頭文件即可。這樣,模塊B中調用模塊A中的函數時,在編譯階段,模塊B雖然找不到該函數,但是並不會報錯;它會在連接階段中從模塊A編譯生成的目標代碼中找到此函數。
與extern對應的關鍵字是static,被它修飾的全局變量和函數只能在本模塊中使用。因此,一個函數或變量只可能被本模塊使用時,其不可能被extern “C”修飾。
(2) 被extern "C"修飾的變量和函數是按照C語言方式編譯和連接的
在定義函數時,如果沒有加關鍵字“static”,或冠以關鍵字“extern”,表示此函數是外部函數:[extern]nbsp;nbsp;函數類型nbsp;nbsp;函數名(函數參數表){……}調用外部函數時,需要對其進行說明:[extern]nbsp;nbsp;函數類型nbsp;nbsp;函數名(參數類型表)[,函數名2(參數類型表2)……];[案例]外部函數應用。(1)文件mainf.cmain(){nbsp;nbsp;externnbsp;voidnbsp;input(…),process(…),output(…);input(…);nbsp;nbsp;process(…);nbsp;nbsp;output(…);}(2)文件subf1.c……externnbsp;nbsp;voidnbsp;input(……)nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;/*定義外部函數*/{……}(3)文件subf2.c……externnbsp;nbsp;voidnbsp;process(……)nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;/*定義外部nbsp;函數*/{……}(4)文件subf3.c……externnbsp;voidnbsp;output(……)nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;/*定義外部函數*/{……}