www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > > 充電吧
[導(dǎo)讀]?extern "C"的主要作用就是為了能夠正確實(shí)現(xiàn)C++代碼調(diào)用其他C語言代碼。加上extern "C"后,會指示編譯器這部分代碼按C語言的進(jìn)行編譯,而不是C++的。由于C++支持函數(shù)重載,因此編譯

?extern "C"的主要作用就是為了能夠正確實(shí)現(xiàn)C++代碼調(diào)用其他C語言代碼。加上extern "C"后,會指示編譯器這部分代碼按C語言的進(jìn)行編譯,而不是C++的。由于C++支持函數(shù)重載,因此編譯器編譯函數(shù)的過程中會將函數(shù)的參數(shù)類型也加到編譯后的代碼中,而不僅僅是函數(shù)名;而C語言并不支持函數(shù)重載,因此編譯C語言代碼的函數(shù)時不會帶上函數(shù)的參數(shù)類型,一般之包括函數(shù)名。

???? 這個功能十分有用處,因?yàn)樵贑++出現(xiàn)以前,很多代碼都是C語言寫的,而且很底層的庫也是C語言寫的,為了更好的支持原來的C代碼和已經(jīng)寫好的C語言庫,需要在C++中盡可能的支持C,而extern "C"就是其中的一個策略。

這個功能主要用在下面的情況:

1、C++代碼調(diào)用C語言代碼

2、在C++的頭文件中使用

3、在多個人協(xié)同開發(fā)時,可能有的人比較擅長C語言,而有的人擅長C++,這樣的情況下也會有用到

給出一個我設(shè)計(jì)的例子:

moduleA、moduleB兩個模塊,B調(diào)用A中的代碼,其中A是用C語言實(shí)現(xiàn)的,而B是利用C++實(shí)現(xiàn)的,下面給出一種實(shí)現(xiàn)方法:

//moduleA頭文件

#ifndef __MODULE_A_H //對于模塊A來說,這個宏是為了防止頭文件的重復(fù)引用

#define __MODULE_A_H

int fun(int, int);

#endif

//moduleA實(shí)現(xiàn)文件moduleA.C //模塊A的實(shí)現(xiàn)部分并沒有改變

#include"moduleA"

int fun(int a, int b)

{

return a+b;

}

//moduleB頭文件

#idndef __MODULE_B_H //很明顯這一部分也是為了防止重復(fù)引用

#define __MODULE_B_H

#ifdef __cplusplus //而這一部分就是告訴編譯器,如果定義了__cplusplus(即如果是cpp文件, extern "C"{ //因?yàn)閏pp文件默認(rèn)定義了該宏),則采用C語言方式進(jìn)行編譯

#include"moduleA.h"

#endif

… //其他代碼

#ifdef __cplusplus

}

#endif

#endif

//moduleB實(shí)現(xiàn)文件 moduleB.cpp //B模塊的實(shí)現(xiàn)也沒有改變,只是頭文件的設(shè)計(jì)變化了

#include"moduleB.h"

int main()

{

cout<<fun(2,3)<<endl;

}

下面是詳細(xì)的介紹:

由于C、C++編譯器對函數(shù)的編譯處理是不完全相同的,尤其對于C++來說,支持函數(shù)的重載,編譯后的函數(shù)一般是以函數(shù)名和形參類型來命名的。

例如函數(shù)void fun(int, int),編譯后的可能是(不同編譯器結(jié)果不同)_fun_int_int(不同編譯器可能不同,但都采用了類似的機(jī)制,用函數(shù)名和參數(shù)類型來命名編譯后的函數(shù)名);而C語言沒有類似的重載機(jī)制,一般是利用函數(shù)名來指明編譯后的函數(shù)名的,對應(yīng)上面的函數(shù)可能會是_fun這樣的名字。

看下面的一個面試題:為什么標(biāo)準(zhǔn)頭文件都有類似的結(jié)構(gòu)?

#ifndef __INCvxWorksh /*防止該頭文件被重復(fù)引用*/

#define __INCvxWorksh

#ifdef __cplusplus???????????? //告訴編譯器,這部分代碼按C語言的格式進(jìn)行編譯,而不是C++的

extern "C"{

#endif

/*…*/

#ifdef __cplusplus

}

#endif

#endif /*end of __INCvxWorksh*/

分析:

顯然,頭文件中編譯宏"#ifndef __INCvxWorksh 、#define __INCvxWorksh、#endif"(即上面代碼中的藍(lán)色部分)的作用是為了防止該頭文件被重復(fù)引用那么

#ifdef __cplusplus (其中__cplusplus是cpp中自定義的一個宏?。?!)

extern "C"{

#endif

#ifdef __cplusplus

}

#endif

的作用是什么呢?

extern "C"包含雙重含義,從字面上可以知道,首先,被它修飾的目標(biāo)是"extern"的;其次,被它修飾的目標(biāo)代碼是"C"的。

被extern "C"限定的函數(shù)或變量是extern類型的

extern是C/C++語言中表明函數(shù)和全局變量的作用范圍的關(guān)鍵字,該關(guān)鍵字告訴編譯器,其申明的函數(shù)和變量可以在本模塊或其他模塊中使用。

記住,下面的語句:

extern int a; 僅僅是一個變量的聲明,其并不是在定義變量a,并未為a分配空間。變量a在所有模塊中作為一種全局變量只能被定義一次,否則會出錯。

通常來說,在模塊的頭文件中對本模塊提供給其他模塊引用的函數(shù)和全局變量以關(guān)鍵字extern生命。例如,如果模塊B要引用模塊A中定義的全局變量和函數(shù)時只需包含模塊A的頭文件即可。這樣模塊B中調(diào)用模塊A中的函數(shù)時,在編譯階段,模塊B雖然找不到該函數(shù),但并不會報錯;它會在鏈接階段從模塊A編譯生成的目標(biāo)代碼中找到該函數(shù)。

extern對應(yīng)的關(guān)鍵字是static,static表明變量或者函數(shù)只能在本模塊中使用,因此,被static修飾的變量或者函數(shù)不可能被extern C修飾。

被extern "C"修飾的變量和函數(shù)是按照C語言方式進(jìn)行編譯和鏈接的:這點(diǎn)很重要!?。?!

上面也提到過,由于C++支持函數(shù)重載,而C語言不支持,因此函數(shù)被C++編譯后在符號庫中的名字是與C語言不同的;C++編譯后的函數(shù)需要加上參數(shù)的類型才能唯一標(biāo)定重載后的函數(shù),而加上extern "C"后,是為了向編譯器指明這段代碼按照C語言的方式進(jìn)行編譯

未加extern "C"聲明時的鏈接方式:

//模塊A頭文件 moduleA.h

#idndef _MODULE_A_H

#define _MODULE_A_H

int foo(int x, int y);

#endif

在模塊B中調(diào)用該函數(shù):

//模塊B實(shí)現(xiàn)文件 moduleB.cpp

#include"moduleA.h"

foo(2,3);

實(shí)際上,在鏈接階段,連接器會從模塊A生成的目標(biāo)文件moduleA.obj中找_foo_int_int這樣的符號!??!,顯然這是不可能找到的,因?yàn)閒oo()函數(shù)被編譯成了_foo的符號,因此會出現(xiàn)鏈接錯誤。

常見的做法可以參考下面的一個實(shí)現(xiàn):

moduleA、moduleB兩個模塊,B調(diào)用A中的代碼,其中A是用C語言實(shí)現(xiàn)的,而B是利用C++實(shí)現(xiàn)的,下面給出一種實(shí)現(xiàn)方法:

//moduleA頭文件

#ifndef __MODULE_A_H //對于模塊A來說,這個宏是為了防止頭文件的重復(fù)引用

#define __MODULE_A_H

int fun(int, int);

#endif

//moduleA實(shí)現(xiàn)文件moduleA.C //模塊A的實(shí)現(xiàn)部分并沒有改變

#include"moduleA"

int fun(int a, int b)

{

return a+b;

}

//moduleB頭文件

#idndef __MODULE_B_H //很明顯這一部分也是為了防止重復(fù)引用

#define __MODULE_B_H

#ifdef __cplusplus //而這一部分就是告訴編譯器,如果定義了__cplusplus(即如果是cpp文件, extern "C"{ //因?yàn)閏pp文件默認(rèn)定義了該宏),則采用C語言方式進(jìn)行編譯

#include"moduleA.h"

#endif

… //其他代碼

#ifdef __cplusplus

}

#endif

#endif

//moduleB實(shí)現(xiàn)文件 moduleB.cpp //B模塊的實(shí)現(xiàn)也沒有改變,只是頭文件的設(shè)計(jì)變化了

#include"moduleB.h"

int main()

{

cout<<fun(2,3)<<endl;

}

extern "C"的使用要點(diǎn)

1. 可以是單一語句

??? extern "C" double sqrt(double);

2. 可以是復(fù)合語句, 相當(dāng)于復(fù)合語句中的聲明都加了extern "C"

??? extern "C"

?? {

????? double sqrt(double);

????? int min(int, int);

? }

3.可以包含頭文件,相當(dāng)于頭文件中的聲明都加了extern "C"

?? extern "C"

? {

??? #i nclude

? }

4. 不可以將extern "C" 添加在函數(shù)內(nèi)部

5. 如果函數(shù)有多個聲明,可以都加extern "C", 也可以只出現(xiàn)在第一次聲明中,后面的聲明會接受第一個鏈接指示符的規(guī)則。

6. 除extern "C", 還有extern "FORTRAN" 等。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

其實(shí)在 c++語言里面const修飾的才算是一個真正的常量,在 c 語言中 const 可以說是個“冒牌貨”。為什么會這樣?其實(shí)是 c++ 編譯器對 const 進(jìn)行了加強(qiáng),當(dāng) c++ 編譯器遇到常量聲明時,不會像 c...

關(guān)鍵字: c++ C語言 const

返回函數(shù)的引用去初始化一個新的引用這個和前面一樣,都是不會產(chǎn)生副本,但是現(xiàn)在是用返回值去初始化一個引用聲明c,也就是說這時候變成了變量temp的別名,在c的生命周期內(nèi)temp是一直有效的,這樣做完全可以。

關(guān)鍵字: c++ 返回值 引用聲明

C++是一種面向?qū)ο蟮母呒壋绦蛟O(shè)計(jì)語言,是C語言的超集。

關(guān)鍵字: c++ C語言

本文詳細(xì)解析extern "C"的底層原理與實(shí)際應(yīng)用。

關(guān)鍵字: extern 底層原理

extern "C"的前世今生

關(guān)鍵字: 代碼 C語言 extern

本文介紹了C語言中extern的三種用法。

關(guān)鍵字: extern 嵌入式

分析:這是Adobe 公司2007 年校園招聘的最新筆試題。這道題除了考察應(yīng)聘者的C++ 基本功底外,還能考察反應(yīng)能力,是一道很好的題目。 在Java 中定義了關(guān)鍵字final ,被final 修飾的

關(guān)鍵字: c++ class

泛型算法中的定制操作很多算法都會比較輸入序列中的元素,通過定制比較動作,可以控制算法按照編程者的意圖工作。本文以string排序?yàn)槔M(jìn)行說明,首先是缺省的排序動作:?vector v{"This","

關(guān)鍵字: c++

為什么是lambda?講了這么多天的lambda表達(dá)式,有一個很基本的問題沒有回答:為什么叫l(wèi)ambda表達(dá)式呢?首先這個lambda就是羅馬字母λ,lambda表達(dá)式即λ表達(dá)式。數(shù)學(xué)上有一個概念叫λ

關(guān)鍵字: c++

? ? ? ? 假設(shè)我們有個函數(shù)用來揭示處理程序的優(yōu)先權(quán),另一個函數(shù)用來在某動態(tài)分配所得的Widget 上進(jìn)行某些帶有優(yōu)先權(quán)的處理:int priority () ; void processWi

關(guān)鍵字: c++ effective
關(guān)閉