探索C 的秘密之詳解extern C

2021-05-24 00:36:15 字數 3149 閱讀 1233

時常在

cpp的**之中看到這樣的**:

1、#ifdef __cplusplus 2、

extern "c" 9、

#endif

這樣的**到底是什麼意思呢?首先,

__cplusplus

是cpp

中的自定義巨集,那麼定義了這個巨集的話表示這是一段

cpp的**,也就是說,上面的**的含義是

:如果這是一段

cpp的**,那麼加入

extern "c"

處理其中的**。

要明白為何使用

extern "c"

,還得從

cpp中對函式的過載處理開始說起。在

c++中,為了支援過載機制,在編譯生成的彙編碼中,要對函式的名字進行一些處理,加入比如函式的返回型別等等.而在

c中,只是簡單的函式名字而已,不會加入其他的資訊

.也就是說

:c++和c

對產生的函式名字的處理是不一樣的.

比如下面的一段簡單的函式,我們看看加入和不加入

extern "c"

產生的彙編**都有哪些變化:

1、int f(void) 2、

在加入extern "c"

的時候產生的彙編**是:

1、.file "test.cxx" 2、

.text 3、

.align 2 4、

.globl _f 5、

.def _f; .scl 2; .type 32; .endef 6、

_f:

7、pushl %ebp 8、

movl %esp

,%ebp 9、

movl $1

,%eax

10、popl %ebp

11、ret

但是不加入了

extern "c"

之後1、

.file "test.cxx" 2、

.text 3、

.align 2 4、

.globl __z1fv 5、

.def __z1fv; .scl 2; .type 32; .endef 6、

__z1fv: 7、

pushl %ebp 8、

movl %esp

,%ebp 9、

movl $1

,%eax

10、popl %ebp

11、ret

兩段彙編**同樣都是使用

gcc -s

命令產生的,所有的地方都是一樣的,唯獨是產生的函式名,乙個是

_f,乙個是

__z1fv

。明白了加入與不加入

extern "c"

之後對函式名稱產生的影響,我們繼續我們的討論

:為什麼需要使用

extern "c"

呢?c++

之父在設計

c++之時,考慮到當時已經存在了大量的

c**,為了支援原來的

c**和已經寫好

c庫,需要在

c++中盡可能的支援c,而

extern "c"

就是其中的乙個策略。

試想這樣的情況

:乙個庫檔案已經用

c寫好了而且執行得很良好,這個時候我們需要使用這個庫檔案,但是我們需要使用

c++來寫這個新的**。如果這個**使用的是

c++的方式鏈結這個

c庫檔案的話,那麼就會出現鏈結錯誤

.我們來看一段**

:首先,我們使用

c的處理方式來寫乙個函式,也就是說假設這個函式當時是用

c寫成的:

1、//f1.c 2、

extern "c" 3、

8、}

編譯命令是

:gcc -c f1.c -o f1.o

產生了乙個叫

f1.o

的庫檔案。再寫一段**呼叫這個

f1函式:

1、// test.cxx、2、

//這個

extern

表示f1

函式在別的地方定義,這樣可以通過

3、//

編譯,但是鏈結的時候還是需要

4、//

鏈結上原來的庫檔案.

5、extern void f1(); 6、

int main() 7、

通過gcc -c test.cxx -o test.o

產生乙個叫

test.o

的檔案。然後,我們使用

gcc test.o f1.o

來鏈結兩個檔案,可是出錯了,錯誤的提示是:

1、test.o(.text + 0x1f):test.cxx: undefine reference to 'f1()'

也就是說,在編譯

test.cxx

的時候編譯器是使用

c++的方式來處理

f1()

函式的,但是實際上鏈結的庫檔案卻是用

c的方式來處理函式的,所以就會出現鏈結過不去的錯誤

:因為鏈結器找不到函式。

因此,為了在

c++**中呼叫用

c寫成的庫檔案,就需要用

extern "c"

來告訴編譯器

:這是乙個用

c寫成的庫檔案,請用

c的方式來鏈結它們。

比如,現在我們有了乙個

c庫檔案,它的標頭檔案是

f.h,產生的

lib檔案是

f.lib

,那麼我們如果要在

c++中使用這個庫檔案,我們需要這樣寫:

1、extern "c" 2、

回到上面的問題,如果要改正鏈結錯誤,我們需要這樣子改寫

test.cxx: 1、

extern "c" 2、

5、int main() 6、

重新編譯並且鏈結就可以過去了.

總結c

和c++

對函式的處理方式是不同的

.extern "c"

是使c++

能夠呼叫

c寫作的庫檔案的乙個手段,如果要對編譯器提示使用

c的方式來處理函式的話,那麼就要使用

extern "c"

來說明。

探索C 的秘密之詳解extern

時常在cpp的 之中看到這樣的 ifdef cplusplus extern c endif 這樣的 到底是什麼意思呢?首先,cplusplus是cpp中的自定義巨集,那麼定義了這個巨集的話表示這是一段cpp的 也就是說,上面的 的含義是 如果這是一段cpp的 那麼加入extern c 處理其中的 ...

探索C 的秘密之詳解extern 「C」

時常在cpp的 之中看到這樣的 ifdef cplusplus extern c endif 這樣的 到底是什麼意思呢?首先,cplusplus是cpp中的自定義巨集,那麼定義了這個巨集的話表示這是一段cpp的 也就是說,上面的 的含義是 如果這是一段cpp的 那麼加入extern c 處理其中的 ...

探索C 的秘密之詳解extern C

時常在cpp的 之中看到這樣的 ifdef cplusplus extern c endif 這樣的 到底是什麼意思呢?首先,cplusplus是cpp中的自定義巨集,那麼定義了這個巨集的話表示這是一段cpp的 也就是說,上面的 的含義是 如果這是一段cpp的 那麼加入extern c 處理其中的 ...