extern 和 extern "C" 區別
(1)extern
學過C/C++(cplusplus/cpp)的人都知道,extern是編程語言中的一種屬性,它表征了變量、函數等類型的作用域(可見性)屬性,是編程語言中的關鍵字。當進行編譯時,該關鍵字告訴編譯器它所聲明的函數和變量等可以在本模塊或者文件以及其他模塊或文件中使用。通常,程序員都只是在“*h”(頭文件)使用該關鍵字以限定變量或函數等類型的屬性,然後在其他模塊或本模塊中使用,如:
/*file1.h*/
extern int i;
/*file2.c 其他文件調用該變量*/
[cpp]
int welcom(void)
{
if (i>0)
{
printf("Hello World!\n");
}
}
(2) extern "C"
C++調用C代碼時候要使用extern "C",extern "C"表明了一種編譯規約。
extern "C"
{
/*采用C編譯器編譯的C語言代碼段*/
}
未加extern “C”聲明時的編譯方式
首先看看C++中對類似C的函數是怎樣編譯的。作為一種面向對象的語言,C++支持函數重載,而過程式語言C則不支持。函數被C++編譯後在符號庫中的名字與C語言的不同。例如,假設某個函數的原型為:
void foo( int x, int y );
該函數被C編譯器編譯後在符號庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都采用了相同的機制,生成的新名字稱為“mangledname”)。_foo_int_int這樣的名字包含了函數名、函數參數數量及類型信息,C++就是靠這種機制來實現函數重載的。例如,在C++中,函數void foo( int x, int y )與void foo( int x, float y)編譯生成的符號是不相同的,後者為_foo_int_float。
加extern "C"聲明時的編譯方式
extern "C"
{
void foo( int x, int y );
}
因為指明void foo( int x, int y );采用C編譯器編譯,所以符號庫中的名字為_foo。在鏈接C的實現文件的時候就能找到foo的實現,否則編譯器會提示 undefine reference foo。
代碼示例
foo.h
[cpp]
#ifdef __cplusplus /*如果采用了C++,如下代碼使用C編譯器;*/
extern "C" /*如果沒有采用C++,順序預編譯代碼段*/
{
#endif
/*采用C編譯器編譯的C語言代碼段*/
extern int foo( int x, int y );
#ifdef __cplusplus /*結束使用C編譯器*/
}
#endif
foo.c foo.h的C實現文件
[cpp]
#include "foo.h"
int foo( int x, int y )
{
return x + y;
}
test.cpp C++調用C函數
[cpp]
#include "foo.h"
#include <stdio.h>
int main()
{
printf("Hello %d\n", foo(1, 2));
return 0;
} www.2cto.com
gcc -c foo.c
g++ -c test.cpp
g++ test.o foo.o -o test
# ./test
Hello 3