C++中extern "C"的用法
學(xué)習(xí)過C++的人都知道,extern關(guān)鍵字可以置于變量或者函數(shù)前,以標(biāo)示變量或者函數(shù)的定義在別的文件中,提示編譯器遇到此變量和函數(shù)時在其他模塊中尋找其定義。這里起到的是聲明作用范圍的用處。另外,extern還可以與”C”連用,作為鏈接指示。本文就此進(jìn)行實(shí)例說明如下:
一、C++名字修飾(Name Mangling)
首先需要從C++的重載說起,在C++中函數(shù)重載指的是幾個函數(shù)的函數(shù)名相同,參數(shù)列表不同。那么當(dāng)生成obj中間文件/目標(biāo)文件的時候,C++編譯器如何區(qū)分這幾個重載函數(shù)呢?可以通過把原函數(shù)名與參數(shù)信息結(jié)合,產(chǎn)生一個獨(dú)特的內(nèi)部名字,這種技術(shù)叫做名字修飾(Name Mangling)。名字修飾規(guī)則沒有一個標(biāo)準(zhǔn),所以不同的編譯器的名字修飾規(guī)則也不一樣。
下面是一組函數(shù),其中f()函數(shù)重載了:
int f (void) { return 1; }
int f (int) { return 0; }
void g (void) { int i = f(), j = f(0); }
f(void)和f(int)是不同的函數(shù),除了函數(shù)名相同以外沒有任何關(guān)系。當(dāng)生成obj目標(biāo)文件時,為了區(qū)分它們,C++編譯器根據(jù)參數(shù)信息進(jìn)行了名字修飾:
int __f_v (void) { return 1; }
int __f_i (int) { return 0; }
void __g_v (void) { int i = __f_v(), j = __f_i(0); }
注意g()也被名字修飾了,雖然沒有任何名字沖突。名字修飾應(yīng)用于C++的任何符號。
二、為什么要使用extern “C”?
C語言中沒有名字修飾(Name Mangling),因?yàn)镃語言不支持函數(shù)重載。但是如果C++中含有C代碼,在編譯時C++編譯器對C代碼的函數(shù)也會進(jìn)行名字修飾,函數(shù)名變了以后,將導(dǎo)致在C運(yùn)行庫中找不到對應(yīng)函數(shù),發(fā)生鏈接錯誤。
// 將下面的代碼保存為.cpp文件,并用C++編譯器編譯
int printf(const char *format,...);
int main()
{
printf("GeeksforGeeks");
return 0;
}
輸出:
/tmp/ccQBO9Im.o:在函數(shù)‘main'中: test.cpp:(.text+0xf):對‘printf(char const*, ...)'未定義的引用 collect2: 錯誤:ld 返回 1
為了防止C++編譯器對C代碼進(jìn)行名字修飾,我們將C代碼用extern “C”進(jìn)行鏈接指定,告訴編譯器,在生成中間文件時,不要對這部分代碼進(jìn)行名字修飾,而是生成符合C規(guī)則的中間符號名。
extern "C"
{
int printf(const char *format,...);
}
int main()
{
printf("Hello!");
return 0;
}
添加了extern “C”鏈接指示后,上面的代碼就能夠正常運(yùn)行了。
附:所有的C風(fēng)格的頭文件(stdio.h, string.h, … 等等)都有在extern “C”下聲明,形式如下:
#ifdef __cplusplus
extern "C" {
#endif
/* Declarations of this file */
#ifdef __cplusplus
}
#endif
相關(guān)文章
C語言掃雷詳細(xì)代碼分步實(shí)現(xiàn)流程
掃雷是電腦上很經(jīng)典的游戲,特意去網(wǎng)上玩了一會,幾次調(diào)試之后,發(fā)現(xiàn)這個比三子棋要復(fù)雜一些,尤其是空白展開算法上和堵截玩家有的一拼,與實(shí)際游戲差別較大,不能使用光標(biāo),下面來詳解每一步分析2022-02-02
詳解C語言的隨機(jī)數(shù)生成及其相關(guān)題目
這篇文章主要介紹了詳解C語言的隨機(jī)數(shù)生成及其相關(guān)題目,作者還列舉了阿里巴巴的一道相關(guān)的面試題,需要的朋友可以參考下2015-08-08
C++小利器之std::bind參數(shù)綁定包裝器的使用詳解
從 C++11 開始,標(biāo)準(zhǔn)庫提供了 std::bind 用于綁定函數(shù) f 和調(diào)用參數(shù),返回一個新可調(diào)用函數(shù)對象 fn,下面就跟隨小編一起深入了解一下std::bind的具體使用吧2023-12-12

