C 中extern C 的用法

2022-10-04 04:18:07 字數 1392 閱讀 4712

學習過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 畢竟是一種...