一個(gè)C程序流程可能是由好幾個(gè)各自編譯程序的一部分構(gòu)成,這種差異一部分根據(jù)一個(gè)一般 稱為連接器(或射頻連接器,載入器)的程序流程合拼成一個(gè)總體。由于編譯器一般每一次只解決一個(gè)文檔,因此 它無法檢驗(yàn)出一些必須 一次掌握好幾個(gè)源程序文檔才可以發(fā)覺的不正確。并且,在很多操作系統(tǒng)中連接器是單獨(dú)于C語言完成的,因而假如上述情況不正確的緣由與C語言有關(guān),連接器對于此事也一樣無計(jì)可施。一些C語言完成帶來了一個(gè)稱之為lint的程序流程,能夠捕捉到很多的該類不正確,但可惜的是并不是所有的C語言完成都保證了該程序流程。假如可以尋找例如lint的程序流程,就一定善加利用,這一點(diǎn)不管怎樣注重都不算過。
C語言中的一個(gè)關(guān)鍵觀念便是各自編譯程序(Separate Compilation),即多個(gè)源程序能夠在不一樣的情況下獨(dú)立開展編譯程序,隨后在適當(dāng)?shù)那闆r下融合到一起??墒牵B接器一般是與C編譯器分離出來的,它不太可能掌握C語言的許多關(guān)鍵點(diǎn)。那麼,連接器是怎么保證把多個(gè)C源程序合拼成一個(gè)總體呢?雖然連接器并不理解C語言,殊不知它卻可以了解程序設(shè)計(jì)語言和運(yùn)行內(nèi)存合理布局。編譯器的義務(wù)便是把C源程序“漢語翻譯”成對連接器更有意義的方式,那樣連接器就可以“了解”C源程序了。
典型性的連接器把有編譯器或匯編器轉(zhuǎn)化成的多個(gè)目標(biāo)模塊,融合成一個(gè)被稱作載入模塊或可執(zhí)行程序的實(shí)體線,該實(shí)體線可以被電腦操作系統(tǒng)立即實(shí)行。在其中,一些目標(biāo)模塊是立即做為鍵入給予給連接器的;而此外一些目標(biāo)模塊則是依據(jù)連接全過程的必須 ,從包含有相近printf涵數(shù)的元件庫中得到的。連接器一般 把目標(biāo)模塊當(dāng)做是一組外界對象(external object)構(gòu)成的。每一個(gè)外界對象意味著著設(shè)備運(yùn)行內(nèi)存中的某些一部分,并根據(jù)一個(gè)外界名字來鑒別。因而,程序流程中的每一個(gè)涵數(shù)和每一個(gè)外界自變量,要是沒有申明為staTIc,就全是一個(gè)外界對象。一些C編譯器會(huì)對靜態(tài)函數(shù)和靜態(tài)變量的名字做一定更改,將她們也做為外界對象。因?yàn)橥ㄟ^了“名字裝飾”,因此 她們不容易與其他原體系文件中的同名的涵數(shù)或同名的自變量產(chǎn)生取名矛盾。
大部分連接器都嚴(yán)禁同一個(gè)載入模塊中的2個(gè)不一樣外界對象有著同樣的名字。殊不知,在好幾個(gè)目標(biāo)模塊融合成一個(gè)載入模塊時(shí),這種目標(biāo)模塊很有可能就包括了重名的外界對象。連接器的一個(gè)關(guān)鍵工作中便是解決這類取名矛盾。解決取名矛盾的比較簡單的辦法便是索性徹底嚴(yán)禁。針對外界對象是涵數(shù)的情況,這類作法自然恰當(dāng),一個(gè)程序流程假如包含2個(gè)同名的的不一樣涵數(shù),編譯器壓根便不應(yīng)當(dāng)接納。而針對外界對象是自變量的情況,難題就顯得很多艱難了。不一樣的連接器對這類情況擁有不一樣的處理方法。
連接器的填寫是一組目標(biāo)模塊或是元件庫。連接器的輸出是一個(gè)載入模塊。連接器讀取目標(biāo)模塊和元件庫,與此同時(shí)轉(zhuǎn)化成載入模塊。對每一個(gè)目標(biāo)模塊中的每一個(gè)外界對象,連接器要查驗(yàn)載入模塊,看是不是已經(jīng)有同名的的外界對象。要是沒有,連接器就將該外界對象加上到載入模塊中;如果有,連接器就需要逐漸解決取名矛盾。
除開外界對象以外,目標(biāo)模塊中還有可能包含了對別的模塊中的外界對象的引入。比如,一個(gè)啟用了涵數(shù)printf的C程序流程所產(chǎn)生的目標(biāo)模塊,就涉及了一個(gè)對涵數(shù)printf的引入。能夠推斷得到,該引入偏向的是一個(gè)坐落于某一元件庫中的外界對象。在連接器轉(zhuǎn)化成載入模塊的環(huán)節(jié)中,它需要與此同時(shí)紀(jì)錄這種外界對象的引入。當(dāng)連接器讀取一個(gè)目標(biāo)模塊時(shí),它務(wù)必分析出這一目標(biāo)模塊中界定的任何外界對象的引入,并做出標(biāo)識(shí)表明這種外界對象不會(huì)再是未定義的。