前面已經深刻了解過extern "C"了,下面進一步探討一下extern 「C」的使用方法。ios
一、 C代碼中包含extern 「C」,C代碼沒法經過編譯([1]中C++中調用C的方法1錯誤)函數
代碼以下:spa
//C代碼頭文件CDemo.h #include <stdio.h> #ifndef C_SRC_DEMO_H #define C_SRC_DEMO_H extern "C" int f(int x,int y); #endif // C_SRC_DEMO_H
//C代碼CDemo.c #include "CDemo.h" int f(int x,int y) { printf("In C file\n"); printf("x + y = %d\n",x+y); return 0; }
在Linux下,$:gcc –c CDemo.c 編譯通不過code
出錯信息以下:blog
結論:在C語言的頭文件中,對其外部函數只能指定爲extern類型,C語言中不支持extern "C"聲明,在.c文件中包含了extern "C"時會出現編譯語法錯誤。編譯器
二、 若是在C頭文件中函數聲明瞭函數(f(int x,int y))爲extern類型,而在C++中包含該頭文件後,再從新聲明並添加上extern "C"(extern int f( int x, int y )),C++文件編譯通不過([1]中C++中調用C的方法2錯誤)io
代碼以下: 編譯
//C代碼頭文件CDemo.h #include <stdio.h> #ifndef C_SRC_DEMO_H #define C_SRC_DEMO_H extern int f(int x,int y); #endif // C_SRC_DEMO_H
//C代碼 CDemo.c #include "CDemo.h" int f(int x,int y) { printf("In C file\n"); printf("x + y = %d\n",x+y); return 0; }
//C++代碼 cppDemo.cpp #include "CDemo.h" #include <iostream> extern "C" int f(int x,int y); int main() { f(2,3); return 0; }
在Linux下,$:gcc -c CDemo.c 能夠經過,並生成CDemo.o文件class
$:g++ -c cppDemo.cpp 編譯出錯stream
出錯信息:
可是還要注意一下兩點:
(1)若是不從新聲明,即C++代碼更改成以下:
//C++代碼 cppDemo.cpp #include "CDemo.h" #include <iostream> int main() { f(2,3); return 0; }
編譯能夠經過,可是將兩個.o文件連接起來生成可執行文件時,會出錯執行狀況以下:
$g++ cppDemo.o CDemo.o –o cppDemo
這說明C++文件沒有找到定義在C文件中的f函數,這是由於該函數被C編譯器編譯後在符號庫中的名字與C++編譯器產生的名字不一樣,如, C編譯器產生的函數f的符號庫中的名字爲:f,而C++編譯器產生的爲_Z1fii(不一樣的編譯器可能生成的名字不一樣,可是都採用了相同的機制,生成的新名字稱爲「mangled name」)。
(2)不管C代碼中聲明有沒有包含關鍵字extern,只要C++中有extern 「C」,連接時便不會出錯。
參考文獻:
[1] 《編寫高質量代碼:改善C++程序的150個建議》,建議19:明白在C++中如何使用C