青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

elva

解析“extern”


link: http://blog.csdn.net/keensword/archive/2005/06/23/401114.aspx

解析“extern

 

 

1、 聲明外部變量

 

 

現(xiàn)代編譯器一般采用按文件編譯的方式,因此在編譯時(shí),各個(gè)文件中定義的全局變量是

互相透明的,也就是說(shuō),在編譯時(shí),全局變量的可見(jiàn)域限制在文件內(nèi)部。下面舉一個(gè)簡(jiǎn)單的例子。創(chuàng)建一個(gè)工程,里面含有A.cppB.cpp兩個(gè)簡(jiǎn)單的C++源文件:

//A.cpp

 

 

int i;

 

 

 

 

void main()

 

 

{

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

//B.cpp

 

 

int i;

 

 

 

 

 

 

      

這兩個(gè)文件極為簡(jiǎn)單,在A.cpp中我們定義了一個(gè)全局變量i,在B中我們也定義了一個(gè)全局變量i

我們對(duì)AB分別編譯,都可以正常通過(guò)編譯,但是進(jìn)行鏈接的時(shí)候,卻出現(xiàn)了錯(cuò)誤,錯(cuò)誤提示如下:

Linking...

 

 

B.obj : error LNK2005: "int i" (?i@@3HA) already defined in A.obj

 

 

Debug/A.exe : fatal error LNK1169: one or more multiply defined symbols found

 

 

Error executing link.exe.

 

 

 

 

A.exe - 2 error(s), 0 warning(s)

 

 

 

 

 

 

 

 

 

 

 

 

       這就是說(shuō),在編譯階段,各個(gè)文件中定義的全局變量相互是透明的,編譯A時(shí)覺(jué)察不到B中也定義了i,同樣,編譯B時(shí)覺(jué)察不到A中也定義了i

但是到了鏈接階段,要將各個(gè)文件的內(nèi)容“合為一體”,因此,如果某些文件中定義的全局變量名相同的話,在這個(gè)時(shí)候就會(huì)出現(xiàn)錯(cuò)誤,也就是上面提示的重復(fù)定義的錯(cuò)誤。

       因此,各個(gè)文件中定義的全局變量名不可相同。

 

 

      

       在鏈接階段,各個(gè)文件的內(nèi)容(實(shí)際是編譯產(chǎn)生的obj文件)是被合并到一起的,因而,定義于某文件內(nèi)的全局變量,在鏈接完成后,它的可見(jiàn)范圍被擴(kuò)大到了整個(gè)程序。

       這樣一來(lái),按道理說(shuō),一個(gè)文件中定義的全局變量,可以在整個(gè)程序的任何地方被使用,舉例說(shuō),如果A文件中定義了某全局變量,那么B文件中應(yīng)可以該變量。修改我們的程序,加以驗(yàn)證:

//A.cpp

 

 

 

 

void main()

 

 

{

 

 

    i = 100; //試圖使用B中定義的全局變量

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

//B.cpp

 

 

int i;

 

 

 

 

 

 

 

 

       編譯結(jié)果如下:

 

 

      

Compiling...

 

 

A.cpp

 

 

C:\Documents and Settings\wangjian\桌面\try extern\A.cpp(5) : error C2065: 'i' : undeclared identifier

 

 

Error executing cl.exe.

 

 

 

 

A.obj - 1 error(s), 0 warning(s)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

       編譯錯(cuò)誤。

       其實(shí)出現(xiàn)這個(gè)錯(cuò)誤是意料之中的,因?yàn)椋何募卸x的全局變量的可見(jiàn)性擴(kuò)展到整個(gè)程序是在鏈接完成之后,而在編譯階段,他們的可見(jiàn)性仍局限于各自的文件。

       編譯器的目光不夠長(zhǎng)遠(yuǎn),編譯器沒(méi)有能夠意識(shí)到,某個(gè)變量符號(hào)雖然不是本文件定義的,但是它可能是在其它的文件中定義的。

      

       雖然編譯器不夠遠(yuǎn)見(jiàn),但是我們可以給它提示,幫助它來(lái)解決上面出現(xiàn)的問(wèn)題。這就是extern的作用了。

       extern的原理很簡(jiǎn)單,就是告訴編譯器:“你現(xiàn)在編譯的文件中,有一個(gè)標(biāo)識(shí)符雖然沒(méi)有在本文件中定義,但是它是在別的文件中定義的全局變量,你要放行!”

       我們?yōu)樯厦娴腻e(cuò)誤程序加上extern關(guān)鍵字:

//A.cpp

 

 

 

 

extern int i;

 

 

void main()

 

 

{

 

 

    i = 100; //試圖使用B中定義的全局變量

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//B.cpp

 

 

int i;

 

 

 

 

 

 

 

 

       順利通過(guò)編譯,鏈接。

 

 

 

 

2、 C++文件中調(diào)用C方式編譯的函數(shù)

 

 

 

 

C方式編譯和C++方式編譯

相對(duì)于CC++中新增了諸如重載等新特性,對(duì)于他們的編譯,必然有一些重要的區(qū)別。

我們將下面的小程序分別按CC++方式編譯,來(lái)探討兩種編譯方式的區(qū)別。

int i;

 

 

 

 

int func(int t)

 

 

{

 

 

         return 0;

 

 

}

 

 

 

 

void main()

 

 

{

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

       C方式編譯的結(jié)果:

COMM     _i  :  DWORD

 

 

 

 

PUBLIC    _func

 

 

 

 

PUBLIC    _main

 

 

 

 

 

 

 

 

 

 

 

 

       C++方式編譯的結(jié)果:

PUBLIC    ?i@@3HA                                               ; i

 

 

 

 

PUBLIC    ?func@@YAHH@Z                                         ; func

 

 

 

 

PUBLIC    _main

 

 

 

 

 

 

 

 

 

 

 

 

       可見(jiàn),C方式編譯下,變量名和函數(shù)名之前被統(tǒng)一加上了一個(gè)下劃線,而C++編譯后的結(jié)果卻復(fù)雜的多,i變成了?i@@3HAfunc變成了?func@@YAHH@ZC++中的這種看似復(fù)雜的命名規(guī)則是為C++中的函數(shù)重載,參數(shù)檢查等特性服務(wù)的。

 

 

 

 

多文件程序中的函數(shù)調(diào)用

 

 

       一般情況下,工程中的文件都是CPP文件(以及頭文件)。如下面的程序僅包含兩個(gè)文件:A.CPPB.CPP

 

 

//A.CPP

 

 

void func();

 

 

 

 

void main()

 

 

{

 

 

         func();

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//B.CPP

 

 

void func()

 

 

{

 

 

}

 

 

 

 

 

 

 

 

 

 

       程序的結(jié)構(gòu)是這樣的:在文件B.CPP中定義了一個(gè)函數(shù)void func()main函數(shù)位于文件A.CPP,在main函數(shù)中調(diào)用了B中定義的函數(shù)func()

       要在A中調(diào)用B中定義的函數(shù),必須要加上該函數(shù)的聲明。如本例中的void func();就是對(duì)函數(shù)func()的聲明。

如果沒(méi)有聲明的話,編譯A.CPP時(shí)就會(huì)出錯(cuò)。因?yàn)榫幾g器的目光只局限于被編譯文件,必須通過(guò)加入函數(shù)聲明來(lái)告訴編譯器:“某個(gè)函數(shù)是定義在其它的文件中的,你要放行!”,這一點(diǎn)跟用extern來(lái)聲明外部全局變量是一個(gè)道理。

       需要注意的是,一般的程序都是通過(guò)包含頭文件來(lái)完成函數(shù)的聲明。拿本例來(lái)說(shuō),一般是創(chuàng)建一個(gè)頭文件B.H,在頭文件中加入聲明語(yǔ)句void func(); 并且在A.CPP中加入包含語(yǔ)句:#include “B.H”

 

 

       C++程序中,頭文件的功能從函數(shù)聲明被擴(kuò)展為類(lèi)的定義。

 

 

 

 

不同編譯方式下的函數(shù)調(diào)用

       如果在工程中,不僅有CPP文件,還有以C方式編譯的C文件,函數(shù)調(diào)用就會(huì)有一些微妙之處。我們將B.CPP改作B.C

 

 

 

 

 

 

//A.CPP

 

 

void func();

 

 

 

 

void main()

 

 

{

 

 

         func();

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//B.C

 

 

void func()

 

 

{

 

 

}

 

 

 

 

 

 

 

 

 

 

       對(duì)A.CPPB.C分別編譯,都沒(méi)有問(wèn)題,但是鏈接時(shí)出現(xiàn)錯(cuò)誤。

Linking...

 

 

A.obj : error LNK2001: unresolved external symbol "void __cdecl func(void)" (?func@@YAXXZ)

 

 

Debug/A.exe : fatal error LNK1120: 1 unresolved externals

 

 

Error executing link.exe.

 

 

 

 

A.exe - 2 error(s), 0 warning(s)

 

 

 

 

 

 

 

 

 

 

 

 

原因就在于不同的編譯方式產(chǎn)生的沖突。

 

 

       對(duì)于文件A,是按照C++的方式進(jìn)行編譯的,其中的func()調(diào)用被編譯成了

call    ?func1@@YAXXZ    

 

 

 

 

 

 

如果B文件也是按照C++方式編譯的,那么B中的func函數(shù)名也會(huì)被編譯器改成?func1@@YAXXZ,這樣的話,就沒(méi)有任何問(wèn)題。

       但是現(xiàn)在對(duì)B文件,是按照C方式編譯的,B中的func函數(shù)名被改成了_func,這樣一來(lái),A中的call ?func1@@YAXXZ這個(gè)函數(shù)調(diào)用就沒(méi)有了著落,因?yàn)樵阪溄悠骺磥?lái),B文件中沒(méi)有名為?func1@@YAXXZ的函數(shù)。

       事實(shí)是,我們編程者知道,B文件中有A中調(diào)用的func函數(shù)的定義,只不過(guò)它是按照C方式編譯的,故它的名字被改成了_func。因而,我們需要通過(guò)某種方式告訴編譯器:“B中定義的函數(shù)func()經(jīng)編譯后命名成了_func,而不是?func1@@YAXXZ,你必須通過(guò)call _func來(lái)調(diào)用它,而不是call ?func1@@YAXXZ。”簡(jiǎn)單的說(shuō),就是告訴編譯器,調(diào)用的func()函數(shù)是以C方式編譯的,fun();語(yǔ)句必須被編譯成call _func;而不是call ?func1@@YAXXZ

      

       我們可以通過(guò)extern關(guān)鍵字,來(lái)幫助編譯器解決上面提到的問(wèn)題。

       對(duì)于本例,只需將A.CPP改成如下即可:

//A.CPP

 

 

extern "C"

 

 

{

 

 

         void func();

 

 

}

 

 

void main()

 

 

{

 

 

         func();

 

 

}

 

 

 

 

      

 

 

 

 

 

 

 

 

 

 

 

 

       察看匯編代碼,發(fā)現(xiàn)此時(shí)的func();語(yǔ)句被編譯成了call _func

3、 補(bǔ)充

 

 

2一樣,仍然是CC++混合編程的情形,考慮下面的程序:

//A.CPP

 

 

 

 

extern int i;

 

 

 

 

void main()

 

 

{

 

 

         i = 100;

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//B.C

 

 

int i;

 

 

 

 

 

 

       程序很簡(jiǎn)單:在文件B.C中定義了一個(gè)全局變量i,在A.CPP中使用了這個(gè)全局變量。

       編譯沒(méi)有問(wèn)題,鏈接時(shí)卻出現(xiàn)錯(cuò)誤:

Linking...

 

 

A.obj : error LNK2001: unresolved external symbol "int i" (?i@@3HA)

 

 

Debug/A.exe : fatal error LNK1120: 1 unresolved externals

 

 

Error executing link.exe.

 

 

 

 

A.exe - 2 error(s), 0 warning(s)

 

 

 

 

 

 

 

 

 

 

 

 

      

       這是因?yàn)椋?/span>C方式編譯下,i被重命名為_i,而在C++方式下,i會(huì)被重命名為?i@@3HA

 

 

因而,我們只用extern int i;來(lái)聲明還不夠,必須告訴編譯器,全局變量i是以C方式編譯的,

 

 

它會(huì)被重命名為_i,而不是?i@@3HA

 

 

 

 

       我們修改A.CPP,如下:

 

 

//A.CPP

 

 

 

 

extern "C"

 

 

{

 

 

         int i;

 

 

}

 

 

void main()

 

 

{

 

 

 

 

         i = 100;

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

       程序正常通過(guò)編譯和鏈接。

 

 

       我們察看一下匯編代碼,發(fā)現(xiàn)語(yǔ)句i = 100;被編譯成了mov  DWORD PTR _i, 100

posted on 2008-08-25 01:20 葉子 閱讀(310) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): C\C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品入口尤物| 国产精品手机在线| 久久精品国产91精品亚洲| 亚洲国产精选| 亚洲五月婷婷| 久久久国产视频91| 欧美亚一区二区| 亚洲欧美日韩成人| 欧美成人激情在线| 亚洲欧美精品| 韩日午夜在线资源一区二区| 麻豆视频一区二区| 亚洲最新视频在线播放| 另类综合日韩欧美亚洲| 久久性天堂网| 亚洲国产一区二区三区在线播| 麻豆视频一区二区| 欧美国产91| 久久国产色av| 一本色道精品久久一区二区三区 | 久久久久久久一区二区三区| 在线中文字幕一区| 欧美成人xxx| 亚洲美女精品成人在线视频| 久久亚洲综合色| 先锋亚洲精品| 亚洲国产一区在线| 国语自产精品视频在线看抢先版结局 | 亚洲激情第一区| 欧美在线视频网站| 99视频精品全部免费在线| 亚洲综合欧美日韩| 一区二区三区免费网站| 日韩视频一区二区| 亚洲精品国产视频| 亚洲国产欧美日韩另类综合| 一区二区欧美在线| 蜜月aⅴ免费一区二区三区| 欧美三区美女| 欧美日韩国产综合视频在线观看| 久久久久在线| 国产精品一区二区三区四区 | 久久久久免费视频| 欧美一区二区三区视频免费播放| 亚洲视频一二| 亚洲宅男天堂在线观看无病毒| 一本久道久久综合狠狠爱| 欧美中文在线观看国产| 久久精品国产亚洲精品| 亚洲另类黄色| 欧美 日韩 国产 一区| 免费不卡中文字幕视频| 国产视频亚洲精品| 狠狠色综合网站久久久久久久| 亚洲一区二区四区| 亚洲理伦电影| 久久国产精品99国产精| 国产精品你懂得| 欧美日韩国产精品专区| 在线观看av不卡| 在线日韩av片| 99re热精品| 在线视频成人| 亚洲精品一区二区三区樱花| 亚洲精品影视| 中文日韩在线| 亚洲美女视频在线观看| 欧美极品在线观看| 国产精品网站视频| 中文欧美日韩| 亚洲天堂激情| 国产精品久久久久国产精品日日| 国产伦精品一区二区三| 午夜精品视频一区| 欧美护士18xxxxhd| 亚洲午夜未删减在线观看| 欧美日韩黄视频| 亚洲一区国产一区| 亚洲一区二区三区精品动漫| 久久精品视频一| 欧美极品一区| 日韩视频中文| 亚洲婷婷综合色高清在线| 国产精品一区免费视频| 久久精品国产亚洲精品| 久久亚洲影院| 亚洲亚洲精品在线观看| 老**午夜毛片一区二区三区| 久久天天躁狠狠躁夜夜爽蜜月 | 欧美一区二区三区的| 欧美成人免费网站| 国产亚洲视频在线| 一本在线高清不卡dvd| 99热精品在线观看| 国产啪精品视频| 亚洲影院在线观看| 欧美一区观看| 夜夜爽av福利精品导航| 午夜在线精品偷拍| 国产精品久久久久一区| 久久精品免费看| 亚洲欧美日韩国产另类专区| 国产精品美女久久久久aⅴ国产馆| 欧美一区免费视频| 欧美成人免费播放| 欧美一区中文字幕| 欧美人在线视频| 最新高清无码专区| 久久影院午夜论| 欧美精品18| 欧美影院视频| 亚洲狼人综合| 国产精品一区二区黑丝| 免费成人av在线看| 亚洲小视频在线| 亚洲国产精品久久久久秋霞蜜臀 | 亚洲欧美三级伦理| 美脚丝袜一区二区三区在线观看 | 欧美日韩国产三级| 麻豆国产精品一区二区三区| 欧美精品久久久久久久免费观看 | 欧美制服丝袜| 亚洲影院色无极综合| 免费视频久久| 久久久精彩视频| 国产精品成人播放| 最新精品在线| 亚洲国产精品久久久| 久久国产精品第一页| 亚洲欧美日韩国产综合精品二区| 欧美成人免费在线观看| 在线观看av不卡| 国产欧美视频一区二区三区| 国产精品网站在线播放| 亚洲日本欧美天堂| 亚洲人成7777| 欧美.com| 欧美电影资源| 亚洲欧洲精品成人久久奇米网| 久久久久久久久久码影片| 性亚洲最疯狂xxxx高清| 国产精品九九| 国产精品一区视频网站| 一本色道久久精品| 亚洲一区二区三区免费在线观看| 欧美精品在欧美一区二区少妇| 亚洲人成在线播放网站岛国| 亚洲欧洲一区二区三区| 欧美jizz19性欧美| 亚洲国产精品传媒在线观看 | 欧美一区二区三区四区高清 | 在线亚洲免费视频| 日韩一级大片在线| 欧美日韩一区二区三区| 中文一区二区| 欧美日一区二区在线观看| 一本一本a久久| 欧美一进一出视频| 久久综合亚州| 免播放器亚洲| 亚洲国产女人aaa毛片在线| 亚洲伦理自拍| 国产精品久久久久久久久久ktv| 日韩视频精品在线观看| 国产精品99久久久久久宅男| 国产精品久久久久久久久久免费| 一区二区三区视频在线播放| 欧美一区激情| 亚洲国产精品成人精品| 欧美日韩国产在线播放网站| 亚洲一区二区欧美日韩| 久久精品国产77777蜜臀| 欧美一区不卡| 午夜精品久久久久久久男人的天堂 | 亚洲国产一区二区三区高清| 中文在线一区| 免费一区视频| 亚洲一区观看| 女女同性精品视频| 一区二区免费在线播放| 亚洲欧美不卡| 免费永久网站黄欧美| 亚洲私人影院在线观看| 韩国一区二区三区在线观看 | 久久午夜视频| 亚洲免费观看在线观看| 久久人人看视频| 亚洲视频一区在线| 红桃视频成人| 国产精品福利在线| 久久精品女人| 中文欧美日韩| 亚洲国产欧美一区二区三区同亚洲 | 亚洲国产精品一区二区第一页| 亚洲小说区图片区| 亚洲电影在线看| 国产偷自视频区视频一区二区| 欧美理论大片| 欧美va日韩va| 久久久久国色av免费观看性色|