<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          到底什么是鏈接,它起到了什么作用?

          共 2417字,需瀏覽 5分鐘

           ·

          2022-02-17 00:00

          ????關(guān)注、星標(biāo)公眾號(hào),直達(dá)精彩內(nèi)容

          來源網(wǎng)絡(luò)素材

          整理:李肖遙


          幾十年以前,計(jì)算機(jī)剛剛誕生,人們編寫程序時(shí),將所有的代碼都寫在同一個(gè)源文件中,經(jīng)過長(zhǎng)期的積累,程序包含了數(shù)百萬行的代碼,以至于人們無法維護(hù)這個(gè)程序了。于是人們開始尋找新的方法,迫切地希望將程序源代碼分散到多個(gè)文件中,一個(gè)文件一個(gè)模塊,以便更好地閱讀和維護(hù),這個(gè)時(shí)候,鏈接器就粉墨登場(chǎng)了。

          一切都是地址

          我們知道,數(shù)據(jù)是保存在內(nèi)存中的,對(duì)于計(jì)算機(jī)硬件來說,必須知道它的地址才能使用。變量名、函數(shù)名等僅僅是地址的一種助記符,目的是在編程時(shí)更加方便地使用數(shù)據(jù),當(dāng)源文件被編譯成可執(zhí)行文件后,這些標(biāo)識(shí)符都不存在了,它們被替換成了數(shù)據(jù)的地址。

          假設(shè)變量 a、b、c 的地址分別為 0X1000、0X1004、0X1008,加法運(yùn)算的機(jī)器指令為 1010,賦值運(yùn)算的機(jī)器指令為 1110,那么在C語言中實(shí)現(xiàn)加法運(yùn)算的代碼為:

          c = a + b;

          生成可執(zhí)行文件后的機(jī)器碼為:

          1010 ?0X1000 ?0X1004 ?//將兩個(gè)數(shù)據(jù)相加的值保存在一個(gè)臨時(shí)區(qū)域
          1110 ?0X1008 ?//將臨時(shí)區(qū)域中的數(shù)據(jù)復(fù)制到地址為0X1008的內(nèi)存中

          編譯器和鏈接器的一項(xiàng)重要任務(wù)就是將助記符替換成地址。

          匯編語言的誕生

          任何程序的執(zhí)行,最終都要依靠計(jì)算機(jī)硬件來完成。現(xiàn)代計(jì)算機(jī)硬件都是大規(guī)模集成電路,它只認(rèn)識(shí)高低兩個(gè)電平(電壓),高電平一般為 5V,用1表示,低電平一般為 0V,用0表示。也就是說,在計(jì)算機(jī)底層,沒有文字、數(shù)字、圖像、視頻等豐富多彩的可視化元素,只有 0 和 1 兩個(gè)二進(jìn)制數(shù)字,這就是機(jī)器語言

          計(jì)算機(jī)剛剛誕生的時(shí)候沒有編程語言,人們直接使用機(jī)器語言(二進(jìn)制)編程。現(xiàn)在假設(shè)有一種跳轉(zhuǎn)指令,它的二進(jìn)制形式為 0001,如果需要執(zhí)行地址為 1010 的代碼,那么可以這樣寫:

          0001 ?1010

          所謂跳轉(zhuǎn),就是在執(zhí)行當(dāng)前代碼塊時(shí)轉(zhuǎn)而執(zhí)行其他的代碼塊。從本質(zhì)上講,C語言中的函數(shù)就是一個(gè)代碼塊,當(dāng)發(fā)生函數(shù)調(diào)用時(shí),就會(huì)執(zhí)行其他的代碼塊,這個(gè)過程就是通過跳轉(zhuǎn)指令來完成的。

          那么現(xiàn)在問題來了,程序并不是一寫好就永遠(yuǎn)不變化的,它可能會(huì)經(jīng)常被修改。比如我們?cè)诘刂?1010 之前插入了其他指令,那么原來的代碼就得往后移動(dòng),上面的跳轉(zhuǎn)指令的跳轉(zhuǎn)地址也得相應(yīng)地調(diào)整。

          在這個(gè)過程中,程序員需要人工重新計(jì)算每個(gè)子程序或者跳轉(zhuǎn)的目標(biāo)地址,這種重新計(jì)算各個(gè)目標(biāo)地址的過程叫做重定位(Relocation)每次程序修改時(shí),這些位置都要重新計(jì)算,十分繁瑣又耗時(shí),并且很容易出錯(cuò)。

          如果程序包含了多個(gè)源文件,就很可能會(huì)有跨文件的跳轉(zhuǎn),這種人工重定位的方式在程序擁有多個(gè)模塊時(shí)會(huì)導(dǎo)致更加嚴(yán)重的問題。

          沒辦法,這種黑暗的程序員生活是沒辦法容忍的,于是先驅(qū)們發(fā)明了匯編語言(Assembly),這相比機(jī)器語言來說是個(gè)很大的進(jìn)步。

          匯編語言使用接近人類的各種符號(hào)和標(biāo)記來幫助記憶,比如用
          jmp表示跳轉(zhuǎn)指令,用func表示一個(gè)子程序(C語言中的函數(shù)就是一個(gè)子程序)的起始地址,這種符號(hào)的方法使得人們從具體的機(jī)器指令和二進(jìn)制地址中解放出來。

          將上面的機(jī)器指令使用匯編代碼來書寫:

          jmp func

          這樣,不管在 func 之前增加或者減少了多少條指令導(dǎo)致 func 的地址發(fā)生了變化,匯編器在每次匯編程序的時(shí)候會(huì)重新計(jì)算 func 這個(gè)符號(hào)的地址,然后把所有使用到 func 的地方修正為新的地址,整個(gè)過程不需要人工參與。對(duì)于一個(gè)有成千上百個(gè)類似的符號(hào)的程序,人們終于擺脫了這種低級(jí)的繁瑣的計(jì)算地址的工作,用一句政治口號(hào)來說就是“極大地解放了生產(chǎn)力”。

          符號(hào)(Symbol)這個(gè)概念隨著匯編語言的普及被廣泛接受,它用來表示一個(gè)地址,這個(gè)地址可能是一段子程序(后來發(fā)展為函數(shù))的起始地址,也可以是一個(gè)變量的地址。

          C語言的誕生

          匯編語言的主要作用是為機(jī)器指令提供了助記符,大部分匯編代碼和機(jī)器指令是一一對(duì)應(yīng)的,這在匯編被發(fā)明的初期確實(shí)令程序員非常欣喜。

          后來隨著軟件規(guī)模的日漸龐大,代碼量開始瘋長(zhǎng),匯編語言的缺點(diǎn)逐漸暴露出來。匯編雖然提供了多種符號(hào),但它依然非常接近計(jì)算機(jī)硬件,程序員要考慮很多細(xì)節(jié)問題和邊界問題,并且不利于模塊化開發(fā),所以后來人們發(fā)明了C語言。

          C語言是比匯編更加高級(jí)的編程語言,極大地提高了開發(fā)效率,以加法為例,C語言只需要一條語句,匯編卻需要四五條。

          模塊化開發(fā)

          現(xiàn)代軟件的規(guī)模往往都很大,動(dòng)輒數(shù)百萬行代碼,程序員需要把它們分散到成百上千個(gè)模塊中。這些模塊之間相互依賴又相互獨(dú)立,原則上每個(gè)模塊都可以單獨(dú)開發(fā)、編譯、測(cè)試,改變一個(gè)模塊中的代碼不需要編譯整個(gè)程序。

          在C語言中,一個(gè)模塊可以認(rèn)為是一個(gè)源文件(.c 文件)。

          在程序被分隔成多個(gè)模塊后,需要解決的一個(gè)重要問題是如何將這些模塊組合成一個(gè)單一的可執(zhí)行程序。在C語言中,模塊之間的依賴關(guān)系主要有兩種:一種是模塊間的函數(shù)調(diào)用,另外一種是模塊間的變量訪問。

          函數(shù)調(diào)用需要知道函數(shù)的首地址,變量訪問需要知道變量的地址,所以這兩種方式可以歸結(jié)為一種,那就是模塊間的符號(hào)引用。

          模塊間依靠符號(hào)來“通信”類似于拼圖版,定義符號(hào)的模塊多出一個(gè)區(qū)域,引用符號(hào)的模塊剛好少了那一塊區(qū)域,兩者剛好完美組合。如下圖所示:

          這種通過符號(hào)將多個(gè)模塊拼接為一個(gè)獨(dú)立的程序的過程就叫做鏈接(Linking)

          ???????????????? ?END ????????????????

          關(guān)注我的微信公眾號(hào),回復(fù)“加群”按規(guī)則加入技術(shù)交流群。

          關(guān)注程序員編程基地,回復(fù)“pdf”獲取程序員必讀經(jīng)典書單,一起編程一起進(jìn)階。



          點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。

          瀏覽 36
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  爱草视频 | 色综合天天色 | 老牛吃嫩一区二区三区 | 久久久久成人精品无码中文字幕 | 大鸡吧插逼视频 |