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

elva

解析“extern”


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

解析“extern

 

 

1、 聲明外部變量

 

 

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

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

//A.cpp

 

 

int i;

 

 

 

 

void main()

 

 

{

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

//B.cpp

 

 

int i;

 

 

 

 

 

 

      

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

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

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)

 

 

 

 

 

 

 

 

 

 

 

 

       這就是說,在編譯階段,各個文件中定義的全局變量相互是透明的,編譯A時覺察不到B中也定義了i,同樣,編譯B時覺察不到A中也定義了i

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

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

 

 

      

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

       這樣一來,按道理說,一個文件中定義的全局變量,可以在整個程序的任何地方被使用,舉例說,如果A文件中定義了某全局變量,那么B文件中應可以該變量。修改我們的程序,加以驗證:

//A.cpp

 

 

 

 

void main()

 

 

{

 

 

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

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

//B.cpp

 

 

int i;

 

 

 

 

 

 

 

 

       編譯結果如下:

 

 

      

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)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

       編譯錯誤。

       其實出現(xiàn)這個錯誤是意料之中的,因為:文件中定義的全局變量的可見性擴展到整個程序是在鏈接完成之后,而在編譯階段,他們的可見性仍局限于各自的文件。

       編譯器的目光不夠長遠,編譯器沒有能夠意識到,某個變量符號雖然不是本文件定義的,但是它可能是在其它的文件中定義的。

      

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

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

       我們?yōu)樯厦娴腻e誤程序加上extern關鍵字:

//A.cpp

 

 

 

 

extern int i;

 

 

void main()

 

 

{

 

 

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

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//B.cpp

 

 

int i;

 

 

 

 

 

 

 

 

       順利通過編譯,鏈接。

 

 

 

 

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

 

 

 

 

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

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

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

int i;

 

 

 

 

int func(int t)

 

 

{

 

 

         return 0;

 

 

}

 

 

 

 

void main()

 

 

{

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

       C方式編譯的結果:

COMM     _i  :  DWORD

 

 

 

 

PUBLIC    _func

 

 

 

 

PUBLIC    _main

 

 

 

 

 

 

 

 

 

 

 

 

       C++方式編譯的結果:

PUBLIC    ?i@@3HA                                               ; i

 

 

 

 

PUBLIC    ?func@@YAHH@Z                                         ; func

 

 

 

 

PUBLIC    _main

 

 

 

 

 

 

 

 

 

 

 

 

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

 

 

 

 

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

 

 

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

 

 

//A.CPP

 

 

void func();

 

 

 

 

void main()

 

 

{

 

 

         func();

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//B.CPP

 

 

void func()

 

 

{

 

 

}

 

 

 

 

 

 

 

 

 

 

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

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

如果沒有聲明的話,編譯A.CPP時就會出錯。因為編譯器的目光只局限于被編譯文件,必須通過加入函數(shù)聲明來告訴編譯器:“某個函數(shù)是定義在其它的文件中的,你要放行!”,這一點跟用extern來聲明外部全局變量是一個道理。

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

 

 

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

 

 

 

 

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

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

 

 

 

 

 

 

//A.CPP

 

 

void func();

 

 

 

 

void main()

 

 

{

 

 

         func();

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//B.C

 

 

void func()

 

 

{

 

 

}

 

 

 

 

 

 

 

 

 

 

       A.CPPB.C分別編譯,都沒有問題,但是鏈接時出現(xiàn)錯誤。

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)生的沖突。

 

 

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

call    ?func1@@YAXXZ    

 

 

 

 

 

 

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

       但是現(xiàn)在對B文件,是按照C方式編譯的,B中的func函數(shù)名被改成了_func,這樣一來,A中的call ?func1@@YAXXZ這個函數(shù)調用就沒有了著落,因為在鏈接器看來,B文件中沒有名為?func1@@YAXXZ的函數(shù)。

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

      

       我們可以通過extern關鍵字,來幫助編譯器解決上面提到的問題。

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

//A.CPP

 

 

extern "C"

 

 

{

 

 

         void func();

 

 

}

 

 

void main()

 

 

{

 

 

         func();

 

 

}

 

 

 

 

      

 

 

 

 

 

 

 

 

 

 

 

 

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

3、 補充

 

 

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

//A.CPP

 

 

 

 

extern int i;

 

 

 

 

void main()

 

 

{

 

 

         i = 100;

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//B.C

 

 

int i;

 

 

 

 

 

 

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

       編譯沒有問題,鏈接時卻出現(xiàn)錯誤:

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)

 

 

 

 

 

 

 

 

 

 

 

 

      

       這是因為,在C方式編譯下,i被重命名為_i,而在C++方式下,i會被重命名為?i@@3HA

 

 

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

 

 

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

 

 

 

 

       我們修改A.CPP,如下:

 

 

//A.CPP

 

 

 

 

extern "C"

 

 

{

 

 

         int i;

 

 

}

 

 

void main()

 

 

{

 

 

 

 

         i = 100;

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

       程序正常通過編譯和鏈接。

 

 

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

posted on 2008-08-25 01:20 葉子 閱讀(312) 評論(0)  編輯 收藏 引用 所屬分類: 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>
            在线视频免费在线观看一区二区| 国产日本欧洲亚洲| 欧美一级欧美一级在线播放| 亚洲黄色免费电影| 久久精品视频在线观看| 亚洲视频在线播放| 亚洲国内高清视频| 国精品一区二区三区| 欧美午夜精品理论片a级大开眼界 欧美午夜精品理论片a级按摩 | 免费中文日韩| 欧美在线视频免费观看| 亚洲午夜精品一区二区| 亚洲精品在线一区二区| 欧美激情成人在线视频| 久久天天狠狠| 久久久7777| 欧美一区三区三区高中清蜜桃| 中文av字幕一区| 日韩一级免费观看| 亚洲免费观看在线观看| 亚洲国产毛片完整版| 亚洲成人中文| 狠久久av成人天堂| 国内外成人在线| 国产亚洲在线观看| 国产一区二区成人久久免费影院| 国产欧美日韩在线观看| 国产精品视频网址| 国产久一道中文一区| 国产精品爽黄69| 国产精品一区二区视频| 国产精品日本精品| 国产日韩精品在线| 国产亚洲欧美色| 国产一区二区三区无遮挡| 国产亚洲美州欧州综合国| 国产小视频国产精品| 国产欧美日韩综合一区在线播放| 国产精品一区二区三区久久 | 宅男精品视频| 亚洲性感激情| 午夜精品久久久久久99热| 欧美一区二区三区在线观看视频| 午夜精品一区二区三区在线| 午夜精品视频在线观看| 久久电影一区| 欧美99在线视频观看| 欧美成人一区二区三区片免费| 欧美精品色综合| 国产精品欧美日韩一区| 国产美女一区二区| 在线观看国产精品网站| 亚洲国产视频一区| 夜夜嗨网站十八久久| 亚洲欧美在线看| 欧美综合国产| 欧美福利电影在线观看| 亚洲精品欧美一区二区三区| 亚洲一区二区三区涩| 欧美一级网站| 欧美a级片网站| 国产精品成人aaaaa网站| 国产伦精品一区二区三区高清| 黄色成人在线网址| 99精品国产在热久久| 亚洲欧美成人在线| 久久综合中文| 99视频在线精品国自产拍免费观看 | 亚洲欧美在线一区二区| 久久一区二区三区超碰国产精品| 欧美国产乱视频| 一区二区三区四区五区视频| 欧美一区网站| 欧美日韩成人在线视频| 国产日韩精品在线| 日韩亚洲欧美一区| 久久精品一二三| 亚洲黄色成人| 欧美一区二区三区在线播放| 欧美精品一区二区三区在线看午夜 | 亚洲欧美日韩国产中文| 老司机aⅴ在线精品导航| 欧美日韩中文字幕| 在线观看日韩专区| 亚洲女人天堂成人av在线| 欧美刺激性大交免费视频| 亚洲永久免费视频| 欧美激情视频给我| 国产一区深夜福利| 亚洲一区二区三区在线视频| 免费不卡在线视频| 亚洲影视在线| 欧美精选午夜久久久乱码6080| 国产日韩在线看| 亚洲一区二区久久| 亚洲欧洲精品一区二区三区| 久久国产精品72免费观看| 欧美午夜精品久久久久久超碰| 91久久夜色精品国产九色| 久久精品免费看| 一区二区三区日韩精品| 欧美激情网站在线观看| 在线成人小视频| 久久九九99视频| 亚洲一区二区三区精品视频| 欧美精品播放| 在线日本高清免费不卡| 久久精品一区蜜桃臀影院| 亚洲天堂av高清| 欧美日韩一区在线视频| 亚洲美女视频网| 欧美激情在线狂野欧美精品| 欧美伊人精品成人久久综合97| 国产精品观看| 亚洲永久精品国产| 99亚洲一区二区| 欧美日韩国产成人高清视频| 亚洲精品日韩久久| 欧美国产日韩一区| 免费观看亚洲视频大全| 亚洲国产日韩综合一区| 久久这里只有| 久久精品一区二区三区中文字幕| 国产在线观看精品一区二区三区| 午夜日韩在线观看| 亚洲欧美日韩中文视频| 国产伦精品一区| 午夜精品一区二区三区在线播放| 99视频一区| 国产精品久久久久久久7电影| 亚洲一区二区三区在线播放| 亚洲私人影院在线观看| 国产精品麻豆va在线播放| 亚洲欧洲av一区二区三区久久| 中文日韩在线| 国产精品午夜视频| 久久精品论坛| 久久久精品午夜少妇| 亚洲成人直播| 亚洲激情一区| 欧美三区在线视频| 欧美一区日韩一区| 久久久久久高潮国产精品视| 1204国产成人精品视频| 亚洲观看高清完整版在线观看| 欧美激情一二区| 亚洲专区欧美专区| 午夜精品国产| 在线日韩成人| 亚洲人成在线观看一区二区| 国产精品大全| 欧美专区日韩视频| 久久久之久亚州精品露出| 亚洲久久一区| 亚洲少妇中出一区| 国产午夜精品一区理论片飘花| 免费观看成人| 欧美日韩mv| 久久精品人人做人人爽| 美脚丝袜一区二区三区在线观看| 一个色综合导航| 欧美一区二区三区四区在线| 亚洲激情在线| 亚洲新中文字幕| 亚洲国产高潮在线观看| 99pao成人国产永久免费视频| 国产区二精品视| 欧美激情2020午夜免费观看| 欧美亚一区二区| 久久亚洲视频| 欧美日韩国产另类不卡| 久久久精品免费视频| 欧美激情1区2区3区| 午夜在线成人av| 美女精品视频一区| 午夜在线视频观看日韩17c| 久久综合色88| 性欧美8khd高清极品| 老司机aⅴ在线精品导航| 亚洲欧美在线高清| 免费看黄裸体一级大秀欧美| 午夜精品一区二区在线观看 | 久久精品91久久久久久再现| 99精品福利视频| 久久大逼视频| 亚洲欧美日韩第一区| 欧美国产高潮xxxx1819| 久久久精品国产免大香伊| 欧美日韩午夜| 欧美福利视频网站| 国产日本欧美一区二区三区在线| 亚洲精品在线视频观看| 在线日韩中文字幕| 亚洲欧美电影在线观看| 99视频精品全国免费| 久久久综合网| 久久久久九九视频| 国产精品羞羞答答| 日韩视频精品在线| 亚洲国产精品一区二区第四页av|