• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            那誰(shuí)的技術(shù)博客

            感興趣領(lǐng)域:高性能服務(wù)器編程,存儲(chǔ),算法,Linux內(nèi)核
            隨筆 - 210, 文章 - 0, 評(píng)論 - 1183, 引用 - 0
            數(shù)據(jù)加載中……

            探索C++的秘密之一詳解extern "C"

                   時(shí)常在cpp的代碼之中看到這樣的代碼:

            #ifdef __cplusplus
            extern "C" {
            #endif

            //一段代碼

            #ifdef __cplusplus
            }

            #endif


                    這樣的代碼到底是什么意思呢?首先,__cplusplus是cpp中的自定義宏,那么定義了這個(gè)宏的話表示這是一段cpp的代碼,也就是說(shuō),上面的代碼的含義是:如果這是一段cpp的代碼,那么加入extern "C"{和}處理其中的代碼.

                    要明白為何使用extern "C",還得從cpp中對(duì)函數(shù)的重載處理開(kāi)始說(shuō)起.在c++中,為了支持重載機(jī)制,在編譯生成的匯編碼中,要對(duì)函數(shù)的名字進(jìn)行一些處理,加入比如函數(shù)的返回類型等等.而在C中,只是簡(jiǎn)單的函數(shù)名字而已,不會(huì)加入其他的信息.也就是說(shuō):C++和C對(duì)產(chǎn)生的函數(shù)名字的處理是不一樣的.

                     比如下面的一段簡(jiǎn)單的函數(shù),我們看看加入和不加入extern "C"產(chǎn)生的匯編代碼都有哪些變化:

            int f(void)
            {
                
            return 1;
            }


                   在加入extern "C"的時(shí)候產(chǎn)生的匯編代碼是:

                .file    "test.cxx"
                .text
                .align 
            2
            .globl _f
                .def    _f;    .scl    
            2;    .type    32;    .endef
            _f:
                pushl    
            %ebp
                movl    
            %esp, %ebp
                movl    $
            1%eax
                popl    
            %ebp
                ret


            但是不加入了extern "C"之后

             .file "test.cxx"
             .text
             .align 
            2
            .globl __Z1fv
             .def __Z1fv; .scl 
            2; .type 32; .endef
            __Z1fv:
             pushl 
            %ebp
             movl 
            %esp, %ebp
             movl $
            1%eax
             popl 
            %ebp
             ret


                    兩段匯編代碼同樣都是使用gcc -S命令產(chǎn)生的,所有的地方都是一樣的,
            唯獨(dú)是產(chǎn)生的函數(shù)名,一個(gè)是_f,一個(gè)是__Z1fv.

                    OK,明白了加入與不加入extern "C"之后對(duì)函數(shù)名稱產(chǎn)生的影響,我們繼續(xù)我們的討論:為什么需要使用extern "C"呢?
                    C++之父在設(shè)計(jì)C++之時(shí),考慮到當(dāng)時(shí)已經(jīng)存在了大量的C代碼,為了支持原來(lái)的C代碼和已經(jīng)寫好C庫(kù),需要在C++中盡可能的支持C,而extern "C"就是其中的一個(gè)策略.

                   試想這樣的情況:一個(gè)庫(kù)文件已經(jīng)用C寫好了而且運(yùn)行得很良好,這個(gè)時(shí)候我們需要使用這個(gè)庫(kù)文件,但是我們需要使用C++來(lái)寫這個(gè)新的代碼.如果這個(gè)代碼使用的是C++的方式鏈接這個(gè)C庫(kù)文件的話,那么就會(huì)出現(xiàn)鏈接錯(cuò)誤.我們來(lái)看一段代碼:首先,我們使用C的處理方式來(lái)寫一個(gè)函數(shù),也就是說(shuō)假設(shè)這個(gè)函數(shù)當(dāng)時(shí)是用C寫成的:

            //f1.c
            extern "C"
            {
            void f1()
            {
                
            return;
            }

            }

            編譯命令是:gcc -c f1.c -o f1.o   產(chǎn)生了一個(gè)叫f1.o的庫(kù)文件.
            再寫一段代碼調(diào)用這個(gè)f1函數(shù):

            // test.cxx
            //這個(gè)extern表示f1函數(shù)在別的地方定義,這樣可以通過(guò)
            //編譯,但是鏈接的時(shí)候還是需要
            //鏈接上原來(lái)的庫(kù)文件.
            extern void f1();

            int main()
            {
                f1();

                
            return 0;
            }


            通過(guò)gcc -c  test.cxx -o test.o 產(chǎn)生一個(gè)叫test.o的文件.
            然后,我們使用gcc test.o f1.o來(lái)鏈接兩個(gè)文件,可是出錯(cuò)了,錯(cuò)誤的提示是:
            test.o(.text + 0x1f):test.cxx: undefine reference to 'f1()'
            也就是說(shuō),在編譯test.cxx的時(shí)候編譯器是使用C++的方式來(lái)處理f1()函數(shù)的,但是實(shí)際上鏈接的庫(kù)文件卻是用C的方式來(lái)處理函數(shù)的,所以就會(huì)出現(xiàn)鏈接過(guò)不去的錯(cuò)誤:因?yàn)殒溄悠髡也坏胶瘮?shù).
                  因此,為了在C++代碼中調(diào)用用C寫成的庫(kù)文件,就需要用extern "C"來(lái)告訴編譯器:這是一個(gè)用C寫成的庫(kù)文件,請(qǐng)用C的方式來(lái)鏈接它們.
                  比如,現(xiàn)在我們有了一個(gè)C庫(kù)文件,它的頭文件是f.h,產(chǎn)生的lib文件是f.lib,那么我們?nèi)绻贑++中使用這個(gè)庫(kù)文件,我們需要這樣寫:

            extern "C"
            {
            #include 
            "f.h"
            }

            回到上面的問(wèn)題,如果要改正鏈接錯(cuò)誤,我們需要這樣子改寫test.cxx:

            extern "C"
            {
            extern void f1();
            }


            int main()
            {
                f1();

                
            return 0;
            }


            重新編譯并且鏈接就可以過(guò)去了.

            總結(jié):C和C++對(duì)函數(shù)的處理方式是不同的.extern "C"是使C++能夠調(diào)用C寫作的庫(kù)文件的一個(gè)手段,如果要對(duì)編譯器提示使用C的方式來(lái)處理函數(shù)的話,那么就要使用extern "C"來(lái)說(shuō)明.

             

             

             

            posted on 2006-01-14 23:52 那誰(shuí) 閱讀(4927) 評(píng)論(12)  編輯 收藏 引用 所屬分類: C\C++

            評(píng)論

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            寫得不錯(cuò)。

            C++因?yàn)楹瘮?shù)有很多種,成員函數(shù)拉,template函數(shù)拉,所以他會(huì)對(duì)函數(shù)名稱進(jìn)行變換。
            C很單純,一般也就是在函數(shù)名稱前面加上一個(gè)_就好了。
            2006-01-16 10:06 | 小明

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            學(xué)習(xí)哈:)
            2006-01-16 17:37 | uestc

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            extern "C"是使C++能夠調(diào)用C寫作的庫(kù)文件的一個(gè)手段
            --------------
            同樣,extern "C"也是使C能夠調(diào)用C++庫(kù)文件的一個(gè)手段。只不過(guò),C不能直接包含帶extern "C"的C++頭文件,需要用extern聲明一下要使用的函數(shù)。
            2006-01-19 17:21 | 力為

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            不同編譯器處理這種修飾名的方法是不同的,這就是為什么有些人不喜歡發(fā)布類庫(kù)的原因,換個(gè)編譯器,就只能重新編譯了。
            2006-01-22 16:38 | feelapi

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            總結(jié)一句話:就是為了方便在C++程序中調(diào)用C程序
            2006-01-24 17:00 | 流氓

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            這篇好像完整點(diǎn)
            http://blog.csdn.net/billyang1983/archive/2006/01/04/570498.aspx
            2006-02-25 01:43 | Kemin

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            寫的亂七八糟的,
            2006-04-08 14:01 |

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            這篇寫的最好最全
            http://blog.csdn.net/keensword/archive/2005/06/23/401114.aspx
            2006-05-12 14:21 | mem

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            你好,我們是一家致力于中國(guó)互聯(lián)網(wǎng)的本地搜索、手機(jī)地圖和位置服務(wù)的創(chuàng)業(yè)型軟件公司。入選2005年最值得關(guān)注的50家商業(yè)網(wǎng)站(www.mapabc.com)。Google、Sina、微軟、中搜、阿里巴巴、中國(guó)移動(dòng)等著名的公司都是圖盟科技的合作伙伴,因業(yè)務(wù)需要,需要招聘一些對(duì)于C++方面比較熟悉的人,我看了你的blog,希望和你交流一下,如果你有意在北京工作,而且愿意從事一些有挑戰(zhàn)性的工作的話,請(qǐng)將簡(jiǎn)歷發(fā)送到hyla_he@126.com,我會(huì)與你聯(lián)系,謝謝
            2006-07-05 13:04 | hyla

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            嗷嗷,抱歉,一年前剛剛離開(kāi)北京現(xiàn)在在深圳,哈~~
            2006-07-05 17:34 | 創(chuàng)系

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            @力為


            編寫C/C++公用的用extern "C"頭文件也是可以的。
            #ifdef __cplusplus
            /*
            C++專用部分,包括 class聲明, 公共函數(shù)的重載等。
            */
            extern "C" {
            #endif /*__cplusplus*/
            /*
            C / C++ 公共部分,包括結(jié)構(gòu)聲明,函數(shù)聲明,變量聲明。
            */

            #ifdef __cplusplus
            }
            #endif /*__cplusplus*/
            2006-08-22 17:27 | yihao

            # re: 探索C++的秘密之一詳解extern "C"  回復(fù)  更多評(píng)論   

            http://donna-matura-zoccola.fatte-tun.info
            http://dvd-de-cul.culs-ugx.info
            http://scopare-cinese-foto.sculaccia-tun.info
            http://elle-suce-son-gendre.succhiano-ugx.info
            http://brazil-fetish-video.sculaccia-tun.info
            http://baise-amatrice.senegalese-ugx.info
            http://coppia-trans-escort-romagna.fatte-tun.info
            http://video-de-sexe-gratuitement.succhiano-ugx.info
            http://pokemon-porno.sculaccia-tun.info
            http://video-sexe-amateur-gratuit.senegalese-ugx.info
            http://ciccione-scopano.sculaccia-tun.info
            http://sexe-amateur-francais.succhiano-ugx.info
            http://eva-henger-gratis-porno-video.gradis-tun.info
            http://france-sexe-gratuit.culs-ugx.info
            http://arrapanti-casalinghe.sculaccia-tun.info
            http://telechargement-gratuit-video-sexe-gratuite.senegalese-ugx.info
            http://intervista-gay-escort.sculaccia-tun.info
            http://gratuit-porno-pute-video.senegalese-ugx.info
            http://fotoracconti-erotici-amatoriali.sculaccia-tun.info
            http://rencontre-sexe-en-moselle.senegalese-ugx.info
            http://racconto-o-storia-porno.gradis-tun.info
            http://bresilienne-qui-baise.culs-ugx.info
            http://foto-orgia-tettona.fatte-tun.info
            http://karine-sexe.culs-ugx.info
            http://video-bella-donna-scopata.fatte-tun.info
            http://sexe-moselle.culs-ugx.info
            http://foto-sesso-vecchio-gratis.gradis-tun.info
            http://mangas-land-sexe-gratuit.succhiano-ugx.info
            http://sakura-sexy-gratis.fatte-tun.info
            http://suce-bite-.com.succhiano-ugx.info
            http://sborra-gola.sculaccia-tun.info
            http://over-blog-sexe-mature.culs-ugx.info
            http://bocchino-hard.fatte-tun.info
            http://la-salope-du-jour.succhiano-ugx.info
            http://hard-core-video-amatoriale.fatte-tun.info
            2007-12-30 08:49 | sdgsdg
            亚洲AV无码久久寂寞少妇| 久久精品无码专区免费青青| 久久精品无码免费不卡| 久久精品国产精品亚洲| 国产精品成人久久久| 97精品久久天干天天天按摩| 久久精品成人欧美大片| 亚洲愉拍99热成人精品热久久 | 精品综合久久久久久888蜜芽| 9久久9久久精品| 婷婷国产天堂久久综合五月| 国产亚洲精久久久久久无码| 色婷婷噜噜久久国产精品12p| 亚洲乱码精品久久久久.. | 性做久久久久久久久浪潮| 久久99国内精品自在现线| 亚洲国产精品成人AV无码久久综合影院 | 精品国产一区二区三区久久久狼| 精品国产福利久久久| 亚洲人成无码久久电影网站| 国产精品天天影视久久综合网| 久久99精品国产麻豆宅宅| 国产精品综合久久第一页| 久久99精品综合国产首页| 亚洲综合伊人久久大杳蕉| 亚洲欧美日韩精品久久亚洲区| 高清免费久久午夜精品| 久久中文骚妇内射| 久久亚洲AV无码精品色午夜麻豆 | 欧美午夜精品久久久久久浪潮| 久久精品国产影库免费看| 久久夜色精品国产噜噜麻豆 | 亚洲AV伊人久久青青草原| 久久久久久综合一区中文字幕 | 久久超碰97人人做人人爱| 久久天天躁狠狠躁夜夜躁2014| 久久国产V一级毛多内射| 久久99热这里只有精品国产| 久久精品国产72国产精福利| 久久久久亚洲AV综合波多野结衣 | 久久青青草视频|