學習過c++的人都知道,extern關鍵字可以置於變數或者函式前,以標示變程式設計客棧量或者函式的定義在別的檔案中,提示編譯器遇到此變數和函式時在其他模組中尋找其定義。這裡起到的是宣告作用範圍的用處。另外,extern還可以與」c」連用,作為鏈結指示。本文就此進行例項說明如下:
一、c++名字修飾(name mangling)
首先需要從c++的過載說起,在c++中函式過載指的是幾個函式的函式名相同,引數列表不同。那麼當生成obj中間檔案/目標檔案的時候,c++編譯器如何區分這幾個過載函式呢?可以通過把原函式名與引數資訊結合,產生乙個獨特的內部名字,這種技術叫做名字修飾(name mangling)。名字修飾規則沒有乙個標準,所以不同的編譯器的名字修飾規則也不一樣。
下面是一組函式,其中f()函式過載了:
int f (void)
int f (int)
void g (void)
f(void)和f(int)是不同的函式,除了函式名相同以外沒有任何關係。當生成obj目標檔案時,為了區分它們,c++編譯器根據引數資訊進行了名字修飾:
int __f_v (void)
int __f_i (int)
void __g_v (void)
注意g()也被名字修飾了,雖然沒有任何名字衝突。名字修飾應用於c++的任何符號。
二、為什麼要使用extern 「c」?
c語言中沒有名字修飾(name mangling),因為c語言不支援函式過載。但是如果c++中含有c**,在編譯時c++編譯器對c**的函式也會進行名字修飾,函式名變了以後,將導致在c執行庫中找不到對應函式,發生鏈結錯誤。
// 將下面的**儲存為.cpp檔案,並用c++編譯器編譯
int printf(const char *format,...);
int main()
輸出:/tmp/ccqbo9i程式設計客棧m.o:在函式『main'中:
test.cpp:(.text+0xf):對『printf(char const*, ...)'未定義的引用
collect2: 錯誤:ld 返回 1
為了防止c++編譯器對c**進行名字修飾,我們將c**用extern 「c」進行鏈結指定,告訴編譯器,在生成中間檔案時,不要對這部分**進行名字修飾,而是生成符合c規則的中間符號名。
extern "c"
int main()
新增了extern 「c」鏈結指示後,上面的**就能夠正常執行了。
附:所有的c風格的標頭檔案(stdio.h, string.h, … 等等)都有在extern 「c」下宣告,形式如下:
#ifdef __cplusplus
extern "c"
#endif
本文標題: c++中extern "c"的用法
本文位址:
原創 C 中 extern C 用法小結
昨天晚上翻 c primer 偶爾看見介紹 extern c 的那一節,看著看著竟然有點糊塗了,覺得書上說的好像有點不對。記得以前也曾經看過這一節,也看過幾篇介紹這個的文章,這次又犯糊塗,看來還是以前沒有搞清楚。後來仔細看了看書上的介紹,又翻了一下 the c programming languag...
extern C 的用法解析
1.引言 c 語言的建立初衷是 a better c 但是這並不意味著c 中類似c語言的全域性變數和函式所採用的編譯和連線方式與c語言完全相同。作為一種欲與c相容的語言,c 保留了一部分過程式語言的特點 被世人稱為 不徹底地物件導向 因而它可以定義不屬於任何類的全域性變數和函式。但是,c 畢竟是一種...
extern C 的用法解析
1.引言 c 語言的建立初衷是 a better c 但是這並不意味著c 中類似c語言的全域性變數和函式所採用的編譯和連線方式與c語言完全相同。作為一種欲與c相容的語言,c 保留了一部分過程式語言的特點 被世人稱為 不徹底地物件導向 因而它可以定義不屬於任何類的全域性變數和函式。但是,c 畢竟是一種...