extern關鍵字主要修飾變量或函數,表示該函數可以跨文件訪問,或者表明該變量在其他文件定義,在此處引用。
1.extern修飾變量
(1)如果某變量int m在a.c中定義聲明,則其他b.c文件訪問時,需要用extern聲明該變量才可以。
注意extern的嚴格聲明,如在一個文件中聲明char a[] = "abcd";另一個文件如果訪問需聲明extern char a[],而不能是extern char *a;
(2)如果在*.h中聲明,其他文件使用時,則只需要包含頭文件即可,無需再聲明,建議只在頭文件中聲明就好了。
注意:extern可以聲明無數次,但只能定義一次,否則會出現鏈接錯誤。另外能夠被其他模塊以extern修飾符引用到的變量通常是全局變量,extern int m可以放在b.c中的任何地方,如果放在代碼塊內,則b.c中訪問m的區域就只能限於代碼塊內。
(3)如果一個變量聲明於代碼塊內部,在它前面添加extern表示引用的是全局變量而不是局部變量。
2.extern修飾函數(不用"C"修飾)
extern修飾函數和變量沒有區別,只需extern聲明后,即可用於該文件中各個位置。對其他模塊中函數的引用,最常用的方法是包含這些函數聲明的頭文件,在程序中取代include “*.h”來聲明函數。
一般調用方式如下:首先在頭文件extern 修飾聲明函數,包含該頭文件在對應的c文件中實現該函數,C語言中其他文件使用時可以直接調用,也可用extern聲明該函數后使用,但C++必須聲明后才能使用。建議聲明后使用。
使用extern和包含頭文件來引用函數有什么區別呢?
extern的引用方式比包含頭文件要簡潔得多!extern的使用方法是直接了當的,想引用哪個函數就用extern聲明哪個函數。這樣做的一個明顯的好處是,會加速程序的編譯(確切的說是預處理)的過程,節省時間。在大型C程序編譯過程中,這種差異是非常明顯的。
3.extern用於C\C++相互調用
extern修飾函數時可以添加"C",從而實現C\C++相互調用。
(1)C調用C++
C++頭文件中函數前用extern "C"修飾聲明,在對應的cpp文件中實現該函數時需注意函數接口不能使用vector或string等C++專有特性,否則C中無法使用
一般調用方式如下:首先在C++頭文件extern "C"修飾聲明函數,包含該頭文件在對應的cpp文件中實現該函數,使用時可以和普通extern聲明函數一樣使用,在C語言中,只能指定為extern類型,C語言中不支持extern"C"聲明。
(2)C++調用C
C++語言在編譯的時候為了解決函數的多態問題,會將函數名和參數聯合起來生成一個中間的函數名稱,而C語言則不會,因此會造成鏈接時找不到對應函數的情況,此時C函數就需要用extern “C”進行鏈接指定,這告訴編譯器,請保持我的名稱,不要生成用於鏈接的中間函數名。
一般調用格式有兩種,第一種在c語言頭文件中用extern"C"聲明:
exte.h
1 #ifdef __cplusplus 2 extern "C" { 3 #endif 4 5 void mytest(); 6 7 #ifdef __cplusplus 8 } 9 #endif
exte.c
1 #include "exte.h" 2 #include <stdio.h> 3 void mytest(){ 4 5 printf("%s", "mytest"); 6 }
main.cpp
1 #include<iostream> 2 //#include "exte.h" 3 extern "C" void mytest();//和上面的語句二選一即可,如果函數太多,一般用上面包含頭文件的方法 4 int main(){ 5 6 mytest(); 7 system("pause"); 8 return 0; 9 }
第二種是在cpp文件調用時,通過extern"C"包含C語言頭文件
exte.h
1 void mytest();
exte.c
1 void mytest(){ 2 3 printf("%s", "mytest"); 4 }
main.cpp
1 #include<iostream> 2 3 extern "C"{ //和下面的語句二選一即可 4 #include "exte.h" 5 } 6 7 //extern "C" void mytest(); 8 9 int main(){ 10 11 mytest(); 12 system("pause"); 13 return 0; 14 }
其中第二種,可以去掉include頭文件,調用時extern "C" void mytest();即可。
綜上,可以在頭文件中聲明,也可以調用時聲明。至於是否需要頭文件,根據實際需要決定。
