剖析extern "C"

env:
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)


在c++中調(diào)用c語言寫的模塊時經(jīng)常在頭文件中加入這樣一段預(yù)處理命令:

#ifdef __cplusplus
extern "C" {   
#endif
/*some c header or declaration*/
#ifdef __cplusplus
}
#endif

之所以要引入extern "C"(注: 引號中是大寫的C), 是因為c++中存在overload即函數(shù)重載, 為了區(qū)別函數(shù)名相同參數(shù)不同的函數(shù), c++編譯器在編譯期間會將函數(shù)名和函數(shù)參數(shù)作為整體進(jìn)行編譯來得到鏈接所需的符號;c語言中沒有overload, 編譯器直接以函數(shù)名作為鏈接符號, 無視函數(shù)名后面的參數(shù)。


請看以下例程:

例程一:

有以下2個模塊main.cc和add.c, 在main.cc中調(diào)用add.c中的函數(shù)add

/*main.cc模塊*/
#include <iostream>

//extern "C"
//{
  extern int add(int a, int b);
//}

int main(int argc, char * argv[])
{
  int s;
  
  s = add(1, 2); 
  std::cout << "s = " << s << std::endl;  

  return 0;
}
/*add.c模塊*/
int add(int a, int b)
{
  return a + b;
}

執(zhí)行以下命令:
g++ -c main.cc
gcc -c add.c
g++ main.o add.o -o test
則會報鏈接錯誤:
undefined reference to `add(int , int)', 意為找不到該函數(shù)定義。
執(zhí)行objdump -t main.o查看符號表發(fā)現(xiàn)main.cc中調(diào)用的外部函數(shù)add已被編譯為"00000000 UND 00000000 _Z3addii"(add后面的2個i為參數(shù)int, int 的縮寫), 明顯函數(shù)編譯后的鏈接符號與函數(shù)參數(shù)是有關(guān)系的。再執(zhí)行objdump -t add.o查看符號表發(fā)現(xiàn)add函數(shù)對應(yīng)的符號就是add。顯而易見鏈接器肯定找不到鏈接符號為_Z3addii的函數(shù), 因為我們從來沒有定義過。

試想: 其他模塊不動將add.c中的add函數(shù)改名為_Z3addii是否可以鏈接成功呢? 答案是肯定的, 但是這么寫代碼有啥意義呢?

例程二:

有以下2個模塊main.cc和add.c, 在main.cc中調(diào)用add.c中的函數(shù)add
將例程一中extern "C"的注釋打開, 如下所示:

/*main.cc模塊*/
#include <iostream>

extern "C"
{
  extern int add(int a, int b);
}

int main(int argc, char * argv[])
{
  int s;
  
  s = add(1, 2);
  std::cout << "s = " << s << std::endl;  

  return 0;
}
/*add.c模塊*/
int add(int a, int b)
{
  return a + b;
}

執(zhí)行以下命令:
g++ -c main.cc
gcc -c add.c
g++ main.o add.o -o test
編譯鏈接正常, 執(zhí)行可執(zhí)行文件./test, 即可看到我們想要的結(jié)果:s = 3。此刻我們再次執(zhí)行命令objdump -t main.o看到main.cc中的調(diào)用的外部函數(shù)add被編譯為:"UND 00000000 add", 符號和函數(shù)名完全一致而沒有添加一些奇怪的東西!

總結(jié):

? extern "C"就是要告訴c++編譯器大括號里面聲明的函數(shù)要按照c語言的方式編譯成鏈接需要的符號。這樣c++在鏈接的時候才能找到對應(yīng)的c函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關(guān)于...
    SeanCST閱讀 8,117評論 0 27
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 3,160評論 0 3
  • 玟瑾/文 食客眾多、就餐需要排隊領(lǐng)號、總在翻臺,人們就會說這個飯館人氣十足,而當(dāng)一個人總表現(xiàn)出一些影響力、具有很強...
    我是玟瑾閱讀 708評論 0 1
  • 青春說起來好像是一個褒義詞,仿佛它就該是絢爛的或難忘或,,,好多詞可以形容它,可我卻只想任性的只寫自己的青春。 我...
    微窨一世閱讀 249評論 5 0
  • 小時候,我們總是亦步亦趨的跟著父母,唯恐做錯了事。上學(xué)后,模仿老師走路、說話,因為覺得老師超級正確。工作了,深知責(zé)...
    葉塞尼婭閱讀 654評論 0 0

友情鏈接更多精彩內(nèi)容